Overview
Banks, finance companies and insurers publish their car-loan and motor-insurance rates on AutoArena. Every vehicle listing is priced from those rates, so buyers see your offer — monthly repayment or annual premium — on each car your rate card covers, and can send you a request in one click.
The API lets your systems do everything the partner portal does:
- Publish and update products and rate cards whenever your pricing changes.
- Test your pricing on any vehicle before it goes live.
- Receive buyer requests instantly by webhook, or poll for them, and record the outcome.
https://dealcentral.ng/api/partner/v1Requests and responses are JSON (UTF-8). Amounts are whole naira. Times are ISO-8601.
Getting started
- Apply for a partner account as a lender or an insurer. Our team checks your CAC registration and CBN / NAICOM licence.
- While you wait, sign in to the partner portal and set up your products. Nothing is shown to buyers until you are approved.
- In the portal, open API & integrations and create an API key. It is shown once — store it as a secret, e.g.
AUTOARENA_API_KEY. - Check it works:
GET /me. Then add a webhook address to receive requests in real time.
Authentication
Send your key in the Authorization header on every call:
Authorization: Bearer aa_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- Keys start with
aa_live_. We keep only a fingerprint of the key, so a lost key cannot be recovered — roll a new one in the portal (the old one stops working immediately). - Keep keys on your servers; never put them in a web page or mobile app.
- API access can be switched off in the portal without deleting the key. Suspended accounts are refused.
Errors & limits
Errors return a JSON body with a machine-readable code:
{
"error": {
"code": "validation_failed",
"message": "Some fields are not valid.",
"fields": {
"rules": [
"Row 2: enter an interest rate above 0 and up to 100% a year."
]
}
}
}
| HTTP | code | Meaning |
|---|---|---|
| 401 | unauthenticated | Missing, wrong or revoked key, or API access switched off. |
| 403 | account_suspended, managed_by_autoarena | Your account is suspended, or AutoArena maintains your rates for you. |
| 404 | not_found | No such product, request or listing on your account. |
| 422 | validation_failed | See fields for what to fix. |
| 429 | rate_limited | More than 120 requests a minute with one key. Wait and retry. |
Reference data
GET/reference returns the ids and values rate cards use: vehicle types and their sub-types, engine types, conditions, cover types, rate bases, request statuses and limits.
| Field | Values |
|---|---|
Vehicle types (vehicle_type) | 1 Cars, 11 Motorcycles & Tricycles, 21 Buses & Microbuses, 29 Trucks & Trailers, 40 Heavy Equipment & Machinery, 51 Personal Mobility, 63 Watercraft & Boats, 75 Aircraft, 85 Vehicle Parts & Accessories, 97 Auto Services, 112 Other Vehicles — each has sub-types (subtype). |
Engine types (engine_type) | petrol Petrol, diesel Diesel, hybrid Hybrid, electric Electric, gas Gas (CNG / LPG) |
Conditions (condition) | Brand New, Tokunbo, Nigerian-Used |
Cover types (cover_type) | comprehensive Comprehensive, third_party_fire_theft Third party, fire & theft, third_party Third party only |
| Request statuses | New, Contacted, Approved, Declined, Closed |
Rate cards
A product carries a rate card: a list of rows, each pricing a slice of vehicles. Leave a field out (or null) to match any value.
| Row field | Type | Matches |
|---|---|---|
vehicle_type | id | The general vehicle type (e.g. Cars). |
subtype | id | A sub-type within it (e.g. SUVs & Crossovers). Implies its vehicle type. |
engine_type | string | General engine type. |
condition | string | Brand New, Tokunbo or Nigerian-Used. |
min_year, max_year | integer | Model year range (a car with no known year never matches a row with a year limit). |
min_price, max_price | naira | Vehicle price range. |
rate | number | Lenders: interest % a year. Insurers: annual premium as % of the vehicle's price. |
fixed_premium | naira | Insurers only: a fixed annual premium instead of a rate (e.g. third party). |
Up to 60 rows per product and 20 products per account. PUT replaces a product together with its whole rate card, so always send every row.
Lenders: loan products
| Field | Required | Notes |
|---|---|---|
name | yes | Shown to buyers, max 120 characters. |
rate_basis | yes | reducing (APR on the reducing balance) or flat (flat interest on the full amount). |
min_down_percent | yes | 0–90. Buyers cannot choose less. |
min_tenor_months, max_tenor_months | yes | 1–120. |
processing_fee_percent | no | One-off fee as % of the loan, shown to the buyer. |
min_loan, max_loan | no | Naira. Above max_loan we raise the down payment so the loan fits (up to 90%). |
description, terms_url, status | no | status is active (default) or paused. |
rules | yes | The rate card, at least one row. |
Monthly repayment on a reducing balance uses the standard amortisation formula; on a flat rate it is (loan + loan × rate × years) ÷ months.
Lenders: publish or update a loan product
PUT replaces the product and its whole rate card (POST /products creates a new one). Send it whenever your rates change.
curl -X PUT "https://dealcentral.ng/api/partner/v1/products/12" \
-H "Authorization: Bearer $AUTOARENA_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "AutoLoan Plus",
"description": "Up to 60 months, 20% down",
"status": "active",
"rate_basis": "reducing",
"min_down_percent": 20,
"min_tenor_months": 12,
"max_tenor_months": 60,
"processing_fee_percent": 1,
"max_loan": 60000000,
"rules": [
{
"rate": 27
},
{
"vehicle_type": 1,
"condition": "Brand New",
"rate": 21
},
{
"vehicle_type": 1,
"subtype": 3,
"engine_type": "electric",
"min_year": 2019,
"rate": 23
},
{
"min_price": 200000000,
"rate": 18
}
]
}'
<?php
$payload = [
'name' => 'AutoLoan Plus',
'description' => 'Up to 60 months, 20% down',
'status' => 'active',
'rate_basis' => 'reducing',
'min_down_percent' => 20,
'min_tenor_months' => 12,
'max_tenor_months' => 60,
'processing_fee_percent' => 1,
'max_loan' => 60000000,
'rules' => [
[
'rate' => 27,
],
[
'vehicle_type' => 1,
'condition' => 'Brand New',
'rate' => 21,
],
[
'vehicle_type' => 1,
'subtype' => 3,
'engine_type' => 'electric',
'min_year' => 2019,
'rate' => 23,
],
[
'min_price' => 200000000,
'rate' => 18,
],
],
];
$ch = curl_init('https://dealcentral.ng/api/partner/v1/products/12');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTOARENA_API_KEY'),
'Content-Type: application/json',
'Accept: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 300) {
throw new RuntimeException("AutoArena API error {$status}: {$body}");
}
$result = json_decode($body, true)['data'];
// Node.js 18+ (built-in fetch)
const payload = {
"name": "AutoLoan Plus",
"description": "Up to 60 months, 20% down",
"status": "active",
"rate_basis": "reducing",
"min_down_percent": 20,
"min_tenor_months": 12,
"max_tenor_months": 60,
"processing_fee_percent": 1,
"max_loan": 60000000,
"rules": [
{
"rate": 27
},
{
"vehicle_type": 1,
"condition": "Brand New",
"rate": 21
},
{
"vehicle_type": 1,
"subtype": 3,
"engine_type": "electric",
"min_year": 2019,
"rate": 23
},
{
"min_price": 200000000,
"rate": 18
}
]
};
const res = await fetch('https://dealcentral.ng/api/partner/v1/products/12', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.AUTOARENA_API_KEY}`,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify(payload),
});
if (!res.ok) throw new Error(`AutoArena API ${res.status}: ${await res.text()}`);
const { data } = await res.json();
import os
import requests
payload = {
"name": "AutoLoan Plus",
"description": "Up to 60 months, 20% down",
"status": "active",
"rate_basis": "reducing",
"min_down_percent": 20,
"min_tenor_months": 12,
"max_tenor_months": 60,
"processing_fee_percent": 1,
"max_loan": 60000000,
"rules": [
{
"rate": 27,
},
{
"vehicle_type": 1,
"condition": "Brand New",
"rate": 21,
},
{
"vehicle_type": 1,
"subtype": 3,
"engine_type": "electric",
"min_year": 2019,
"rate": 23,
},
{
"min_price": 200000000,
"rate": 18,
},
],
}
r = requests.put(
"https://dealcentral.ng/api/partner/v1/products/12",
json=payload,
headers={"Authorization": f"Bearer {os.environ['AUTOARENA_API_KEY']}"},
timeout=15,
)
r.raise_for_status()
result = r.json()["data"]
Insurers: insurance products
| Field | Required | Notes |
|---|---|---|
name | yes | Shown to buyers. |
cover_type | yes | comprehensive, third_party_fire_theft, third_party |
min_premium | no | Naira. The premium is never below this. |
description, terms_url, status | no | |
rules | yes | Each row has a rate or a fixed_premium. |
Third-party cover with a fixed premium is one row: {"name": "Third Party", "cover_type": "third_party", "rules": [{"fixed_premium": 15000}]}.
Insurers: publish or update an insurance product
Rows use a premium rate (% of the vehicle value per year) or a fixed_premium, e.g. for third-party cover.
curl -X PUT "https://dealcentral.ng/api/partner/v1/products/31" \
-H "Authorization: Bearer $AUTOARENA_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Comprehensive Motor",
"status": "active",
"cover_type": "comprehensive",
"min_premium": 150000,
"rules": [
{
"rate": 3.5
},
{
"vehicle_type": 1,
"condition": "Brand New",
"rate": 2.5
},
{
"engine_type": "electric",
"rate": 4
}
]
}'
<?php
$payload = [
'name' => 'Comprehensive Motor',
'status' => 'active',
'cover_type' => 'comprehensive',
'min_premium' => 150000,
'rules' => [
[
'rate' => 3.5,
],
[
'vehicle_type' => 1,
'condition' => 'Brand New',
'rate' => 2.5,
],
[
'engine_type' => 'electric',
'rate' => 4,
],
],
];
$ch = curl_init('https://dealcentral.ng/api/partner/v1/products/31');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTOARENA_API_KEY'),
'Content-Type: application/json',
'Accept: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 300) {
throw new RuntimeException("AutoArena API error {$status}: {$body}");
}
$result = json_decode($body, true)['data'];
// Node.js 18+ (built-in fetch)
const payload = {
"name": "Comprehensive Motor",
"status": "active",
"cover_type": "comprehensive",
"min_premium": 150000,
"rules": [
{
"rate": 3.5
},
{
"vehicle_type": 1,
"condition": "Brand New",
"rate": 2.5
},
{
"engine_type": "electric",
"rate": 4
}
]
};
const res = await fetch('https://dealcentral.ng/api/partner/v1/products/31', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.AUTOARENA_API_KEY}`,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify(payload),
});
if (!res.ok) throw new Error(`AutoArena API ${res.status}: ${await res.text()}`);
const { data } = await res.json();
import os
import requests
payload = {
"name": "Comprehensive Motor",
"status": "active",
"cover_type": "comprehensive",
"min_premium": 150000,
"rules": [
{
"rate": 3.5,
},
{
"vehicle_type": 1,
"condition": "Brand New",
"rate": 2.5,
},
{
"engine_type": "electric",
"rate": 4,
},
],
}
r = requests.put(
"https://dealcentral.ng/api/partner/v1/products/31",
json=payload,
headers={"Authorization": f"Bearer {os.environ['AUTOARENA_API_KEY']}"},
timeout=15,
)
r.raise_for_status()
result = r.json()["data"]
Test your pricing
POST/quote prices a vehicle against your products — active or paused, before or after approval — and shows which row matched. Send a live listing_id, or describe a vehicle with price and any of vehicle_type, subtype, engine_type, condition, year.
Test your pricing on a vehicle
Prices a described vehicle (or a live listing_id) against your own products, even before approval.
curl -X POST "https://dealcentral.ng/api/partner/v1/quote" \
-H "Authorization: Bearer $AUTOARENA_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"price": 38000000,
"vehicle_type": 1,
"subtype": 4,
"engine_type": "hybrid",
"condition": "Brand New",
"year": 2022
}'
<?php
$payload = [
'price' => 38000000,
'vehicle_type' => 1,
'subtype' => 4,
'engine_type' => 'hybrid',
'condition' => 'Brand New',
'year' => 2022,
];
$ch = curl_init('https://dealcentral.ng/api/partner/v1/quote');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTOARENA_API_KEY'),
'Content-Type: application/json',
'Accept: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 300) {
throw new RuntimeException("AutoArena API error {$status}: {$body}");
}
$result = json_decode($body, true)['data'];
// Node.js 18+ (built-in fetch)
const payload = {
"price": 38000000,
"vehicle_type": 1,
"subtype": 4,
"engine_type": "hybrid",
"condition": "Brand New",
"year": 2022
};
const res = await fetch('https://dealcentral.ng/api/partner/v1/quote', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AUTOARENA_API_KEY}`,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify(payload),
});
if (!res.ok) throw new Error(`AutoArena API ${res.status}: ${await res.text()}`);
const { data } = await res.json();
import os
import requests
payload = {
"price": 38000000,
"vehicle_type": 1,
"subtype": 4,
"engine_type": "hybrid",
"condition": "Brand New",
"year": 2022,
}
r = requests.post(
"https://dealcentral.ng/api/partner/v1/quote",
json=payload,
headers={"Authorization": f"Bearer {os.environ['AUTOARENA_API_KEY']}"},
timeout=15,
)
r.raise_for_status()
result = r.json()["data"]
Buyer requests
When a buyer chooses your offer and agrees to share their details with you, a request is created and sent to you. The figures are recalculated on our side from your published rates, never taken from the buyer's browser.
GET/leads lists your requests, oldest first (filters: status, since; paging: page, per_page up to 100). GET/leads/{reference} returns one. A loan request looks like this (insurance requests carry quote.annual_premium and product.cover instead):
{
"data": {
"reference": "AA-L-7KQ2M9P",
"type": "loan",
"status": "New",
"created_at": "2026-10-01T09:14:05+01:00",
"buyer": {
"name": "Chidi Okafor",
"phone": "0803 000 0000",
"email": "chidi@example.com"
},
"vehicle": {
"listing_id": 5,
"title": "2022 Nissan Frontier PRO 4X",
"price": 38000000,
"url": "https://dealcentral.ng/listing/2022-nissan-frontier-pro-4x",
"year": "2022",
"condition": "Brand New",
"engine_type": "hybrid",
"category": "Cars",
"subcategory": "Pickup Trucks"
},
"product": {
"id": 12,
"name": "AutoLoan Plus"
},
"note": null,
"quote": {
"down_payment_percent": 20,
"tenor_months": 60,
"rate_percent": 21,
"rate_basis": "reducing",
"monthly_repayment": 822422
}
}
}
Fetch new buyer requests
Poll this, or receive them instantly by webhook. since= returns requests created after that time.
curl "https://dealcentral.ng/api/partner/v1/leads?status=New&since=2026-10-01T00:00:00Z" \
-H "Authorization: Bearer $AUTOARENA_API_KEY" \
-H "Accept: application/json"
<?php
$ch = curl_init('https://dealcentral.ng/api/partner/v1/leads?status=New&since=2026-10-01T00:00:00Z');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AUTOARENA_API_KEY'), 'Accept: application/json'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
foreach ($response['data'] as $lead) {
// $lead['reference'], $lead['buyer']['phone'], $lead['vehicle']['title'], $lead['quote']
}
const res = await fetch('https://dealcentral.ng/api/partner/v1/leads?status=New&since=2026-10-01T00:00:00Z', {
headers: { Authorization: `Bearer ${process.env.AUTOARENA_API_KEY}`, Accept: 'application/json' },
});
if (!res.ok) throw new Error(`AutoArena API ${res.status}`);
const { data: leads, meta } = await res.json();
for (const lead of leads) {
// lead.reference, lead.buyer.phone, lead.vehicle.title, lead.quote
}
import os
import requests
r = requests.get(
"https://dealcentral.ng/api/partner/v1/leads?status=New&since=2026-10-01T00:00:00Z",
headers={"Authorization": f"Bearer {os.environ['AUTOARENA_API_KEY']}"},
timeout=15,
)
r.raise_for_status()
for lead in r.json()["data"]:
print(lead["reference"], lead["buyer"]["phone"], lead["vehicle"]["title"])
Record the outcome of a request
Status is one of New, Contacted, Approved, Declined, Closed; the note is private to you.
curl -X PATCH "https://dealcentral.ng/api/partner/v1/leads/AA-L-7KQ2M9P" \
-H "Authorization: Bearer $AUTOARENA_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"status": "Contacted",
"note": "Called; collecting documents"
}'
<?php
$payload = [
'status' => 'Contacted',
'note' => 'Called; collecting documents',
];
$ch = curl_init('https://dealcentral.ng/api/partner/v1/leads/AA-L-7KQ2M9P');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTOARENA_API_KEY'),
'Content-Type: application/json',
'Accept: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 300) {
throw new RuntimeException("AutoArena API error {$status}: {$body}");
}
$result = json_decode($body, true)['data'];
// Node.js 18+ (built-in fetch)
const payload = {
"status": "Contacted",
"note": "Called; collecting documents"
};
const res = await fetch('https://dealcentral.ng/api/partner/v1/leads/AA-L-7KQ2M9P', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.AUTOARENA_API_KEY}`,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify(payload),
});
if (!res.ok) throw new Error(`AutoArena API ${res.status}: ${await res.text()}`);
const { data } = await res.json();
import os
import requests
payload = {
"status": "Contacted",
"note": "Called; collecting documents",
}
r = requests.patch(
"https://dealcentral.ng/api/partner/v1/leads/AA-L-7KQ2M9P",
json=payload,
headers={"Authorization": f"Bearer {os.environ['AUTOARENA_API_KEY']}"},
timeout=15,
)
r.raise_for_status()
result = r.json()["data"]
Webhooks
Add an https address in the portal and we POST each event to it as it happens. Respond with any 2xx status within 5 seconds; redirects are not followed. The address must be on the public internet.
| Event | When | data |
|---|---|---|
lead.created | A buyer sends you a request. | The request, exactly as GET /leads/{reference} returns it. |
ping | You press "Send test event" in the portal. | {"message": "Test event from AutoArena", ...} |
POST /your/webhook HTTP/1.1
Content-Type: application/json
User-Agent: AutoArena-Webhooks/1.0
X-AutoArena-Event: lead.created
X-AutoArena-Signature: t=1790000000,v1=5f3c…
{
"id": "evt_3k9d0q2m1x7v4b8n5c6z",
"type": "lead.created",
"created_at": "2026-10-01T09:14:06+01:00",
"data": {
"reference": "AA-L-7KQ2M9P",
"…": "…"
}
}
Verifying the signature
v1 is the hex HMAC-SHA256 of <t>.<raw request body> using your signing secret (whsec_…, shown in the portal). Compare in constant time and reject events whose t is more than 5 minutes old. Each event is sent once; if your endpoint was down, fetch anything you missed with GET /leads?since=….
Receive and verify a webhook
Check the signature before trusting the event, and reject stale timestamps (older than 5 minutes).
# Webhooks are sent by AutoArena to your https endpoint.
# Use "Send test event" on the portal's API page to deliver a signed "ping",
# then point your receiver's logs at the X-AutoArena-* headers.
<?php
// e.g. https://api.your-bank.ng/autoarena/webhook
$secret = getenv('AUTOARENA_WEBHOOK_SECRET'); // whsec_...
$body = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_AUTOARENA_SIGNATURE'] ?? ''; // t=1727700000,v1=...
parse_str(str_replace(',', '&', $header), $sig);
$expected = hash_hmac('sha256', ($sig['t'] ?? '') . '.' . $body, $secret);
if (empty($sig['v1']) || !hash_equals($expected, $sig['v1']) || abs(time() - (int) $sig['t']) > 300) {
http_response_code(400);
exit('invalid signature');
}
$event = json_decode($body, true);
if ($event['type'] === 'lead.created') {
$lead = $event['data']; // reference, buyer, vehicle, product, quote
// create the application in your system, then answer quickly:
}
http_response_code(200);
import crypto from 'node:crypto';
import express from 'express';
const app = express();
// raw body: the signature covers the exact bytes we sent
app.post('/autoarena/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const sig = Object.fromEntries(
(req.get('X-AutoArena-Signature') || '').split(',').map((p) => p.split('=')),
);
const expected = crypto
.createHmac('sha256', process.env.AUTOARENA_WEBHOOK_SECRET)
.update(`${sig.t}.${req.body}`)
.digest('hex');
const valid = sig.v1 && sig.v1.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(sig.v1), Buffer.from(expected))
&& Math.abs(Date.now() / 1000 - Number(sig.t)) < 300;
if (!valid) return res.status(400).send('invalid signature');
const event = JSON.parse(req.body);
if (event.type === 'lead.created') {
const lead = event.data; // reference, buyer, vehicle, product, quote
}
res.sendStatus(200);
});
app.listen(3000);
import hashlib
import hmac
import json
import os
import time
from flask import Flask, abort, request
app = Flask(__name__)
@app.post("/autoarena/webhook")
def autoarena_webhook():
body = request.get_data() # raw bytes, exactly as sent
sig = dict(p.split("=", 1) for p in request.headers.get("X-AutoArena-Signature", "").split(",") if "=" in p)
expected = hmac.new(
os.environ["AUTOARENA_WEBHOOK_SECRET"].encode(),
sig.get("t", "").encode() + b"." + body,
hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(expected, sig.get("v1", "")) or abs(time.time() - int(sig.get("t", 0))) > 300:
abort(400)
event = json.loads(body)
if event["type"] == "lead.created":
lead = event["data"] # reference, buyer, vehicle, product, quote
return "", 200
All endpoints
GET/me | Your account. |
GET/reference | Ids and values for rate cards. |
GET/products | Your products with their rate cards. |
POST/products | Create a product (201). |
GET/products/{id} | One product. |
PUT/products/{id} | Replace a product and its whole rate card. |
PATCH/products/{id}/status | {"status": "active" | "paused"} |
DELETE/products/{id} | Delete a product. |
POST/quote | Price a vehicle with your products. |
GET/leads | Your buyer requests. |
GET/leads/{reference} | One request. |
PATCH/leads/{reference} | {"status": "...", "note": "..."} |
Questions about integrating? Contact us. Not a partner yet? Apply here.