Partner API Integration Guide
This guide is for third-party partners, DMS/CRM vendors, and dealer data teams who want to exchange data with CarBuddy — either by pushing customer records into CarBuddy for AI-led follow-up, or by pulling lead and conversation data out for their own systems.
If you are a dealer looking to upload a one-off file, see CSV Upload. If you want a recurring automated file feed, see SFTP. This page focuses on the programmatic REST API and how the pieces fit together.
Integration at a glance
CarBuddy supports integration in both directions:
| Direction | What it does | Method |
|---|---|---|
| Partner → CarBuddy | Push customer/vehicle records so CarBuddy runs AI-led email/SMS follow-up | Enrollment REST API or SFTP / CSV feed |
| CarBuddy → Partner | Send you qualified leads and event notifications as they happen | Outbound webhooks |
| Partner → CarBuddy (read) | Pull your leads, conversations and outcomes into your CRM/BI | Portal Data API |
Choose the method that fits your systems:
- Real-time / event-driven → Enrollment REST API (one HTTP call per batch).
- Scheduled bulk files → SFTP feed (drop a CSV, we collect it).
- Manual / occasional → CSV upload in the portal.
You can combine methods — for example, push records via the API and pull outcomes via the Portal Data API.
Authentication
All programmatic access uses an API key presented in a request header. Keys are issued per client by your CarBuddy account manager — there is no public self-service signup.
| Surface | Base URL | Header | Key format |
|---|---|---|---|
| Enrollment / Campaign API | https://engine.carbuddyai.com | X-Api-Key | cb_… |
| Portal Data API | https://portal.carbuddyai.com | X-API-Key | cb_live_… |
| SFTP feed | sftp.carbuddy.uk:30022 | SSH key | ED25519 / RSA |
API keys are equivalent to a password. Send them only over HTTPS, store them in a secret manager (never in source control), and rotate them if you suspect exposure. Contact your account manager to revoke or reissue a key.
Keys are scoped to a single client slug (e.g. eden-motor); presenting a key against a different slug returns 401. Each key carries its own request rate limit — 60 requests per minute by default, raisable per integration on request. Requests over the limit receive 429 Too Many Requests with a Retry-After header giving the seconds to wait.
Because a single request accepts up to 10,000 recipients, the default limit is generous for batch enrolment; it constrains per-record chatter, not volume.
1. Enrollment REST API
The enrollment endpoint is the primary way to push customer records into a CarBuddy campaign. One call enrolls a batch of recipients; CarBuddy then runs the AI-led email/SMS sequence, handles replies, classifies leads, and hands qualified leads back to your team.
Endpoint
POST https://engine.carbuddyai.com/webhook/{clientSlug}/enroll
| Header | Value |
|---|---|
X-Api-Key | Your cb_… key (scoped to {clientSlug}) |
Content-Type | application/json |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
campaign_type | string | ✅ | The campaign to enrol into, e.g. lost-sales, evhc. Your account manager confirms the value(s) available to you. |
label | string | — | A free-text batch label for your own tracking, e.g. "March 2026 Service Due". |
recipients | array | ✅ | 1–10,000 recipient objects (see below). |
Each object in recipients:
| Field | Type | Required | Description |
|---|---|---|---|
first_name | string | ✅ | Customer first name. If you only have a title (e.g. "Mr Patel") with no forename, put the title here rather than duplicating the surname. |
last_name | string | — | Customer surname. |
email | string | ✅ | Customer email. Rows with a malformed email are skipped (reported back), not fatal to the batch. |
mobile | string | — | Mobile number, ideally E.164 (+447700123456). Other formats are normalised. |
vehicle | string | — | Vehicle description, e.g. "Volkswagen Golf 1.5 TSI". |
vehicle_reg | string | — | Registration plate. If make/model are blank, this triggers a DVLA/MOT lookup to enrich the record. |
manufacturer | string | — | Vehicle make, e.g. "Volkswagen". |
dealer | string | — | Dealership or selling site name. |
assigned_branch | string | — | Branch name used for lead routing in the portal. |
service_date | string | — | Date anchor for countdown-scheduled campaigns (ISO YYYY-MM-DD). |
salutation | string | — | Title (Mr/Mrs/Ms/…). |
opted_in_sms | boolean | — | SMS marketing consent (PECR). Send false to suppress SMS for this contact. Omitting the field does not suppress SMS — see Consent & data protection. |
opted_in_email | boolean | — | Email marketing consent. Send false to suppress email for this contact. Omitting the field does not suppress email. |
false, not an omissionBoth consent flags are three-state: true (consented), false (blocked — we will not send on that channel), and absent/null (unknown — we will send). If your export cannot distinguish "not consented" from "no data", filter non-consenting contacts out of the payload before you send it rather than relying on the field being omitted.
For electronic vehicle health check (EVHC) campaigns, additional per-row fields drive routing and message content — vhc_date, sale_outcome, rag_status, work_details, and a metadata.findings[] array. Ask your account manager for the EVHC field spec if you are integrating that campaign type.
Example request
curl -X POST https://engine.carbuddyai.com/webhook/eden-motor/enroll \
-H "X-Api-Key: cb_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"campaign_type": "lost-sales",
"label": "March 2026 Import",
"recipients": [
{
"first_name": "Sarah",
"last_name": "Jones",
"email": "sarah.jones@example.com",
"mobile": "+447700900456",
"vehicle": "Ford Kuga 1.5 EcoBoost",
"vehicle_reg": "DK21 ABC",
"manufacturer": "Ford",
"dealer": "Eden Motor Group",
"opted_in_sms": true,
"opted_in_email": true
}
]
}'
Responses
| Status | Meaning |
|---|---|
201 Created | Batch accepted — see the response body below. A 201 does not mean every row enrolled. |
400 Bad Request | Validation error — the body's details array names the failing field and row index. |
401 Unauthorized | Missing, invalid, expired, or wrong-client API key. |
404 Not Found | Unknown client slug. |
409 Conflict | The campaign has an end date that has passed. Body carries campaign_type and end_date. |
422 Unprocessable Entity | Batch failed a data-quality gate (e.g. the surname mapped into both name columns). Nothing was enrolled — fix the batch and resubmit. |
429 Too Many Requests | Rate limit exceeded; retry after the Retry-After header value. |
Success body
{
"batchId": 123,
"enrolled": 96,
"duplicates": 3,
"suppressed": 1,
"skipped": [
{ "idx": 12, "reason": "invalid_email" },
{ "idx": 40, "reason": "duplicate_email_active" },
{ "idx": 71, "reason": "suppressed" }
]
}
| Field | Description |
|---|---|
batchId | Batch identifier — use it to find the upload in the portal. |
enrolled | Rows that actually entered the campaign. |
duplicates | Rows collapsed as duplicates (already-active contacts + repeats within this batch). |
suppressed | Rows dropped because the contact has previously opted out or bounced. |
skipped | Per-row drop list. idx is the zero-based index into the recipients array you sent, so you can map each entry back to your source record. |
warning | Present when rows enrolled without dealer or assigned_branch — those messages render with a blank dealer name. |
skippedenrolled is frequently lower than the number of recipients you sent, and that is usually correct behaviour (duplicates, opt-outs, malformed emails). Log the skipped array on your side — it is the only place the per-row reason is reported.
Common skipped reasons: invalid_email, duplicate_email_active, duplicate_email_within_batch, duplicate_branch_service_date, suppressed, lost_sales_cycle_cap.
What happens after enrollment
CarBuddy automatically:
- De-duplicates against customers already active in a campaign (by email or mobile).
- Suppresses anyone who has unsubscribed or is active in a conflicting campaign.
- Enriches records from the registration plate where make/model are missing.
- Starts the AI-led email/SMS sequence and handles inbound replies.
- Classifies each conversation and hands qualified leads to your team (see Outbound webhooks).
2. Checking batch and recipient status
Once a batch is enrolled you can monitor progress in the portal under Upload History and Leads.
Programmatic read endpoints also exist under https://engine.carbuddyai.com/api/v1/{clientSlug}/… for batch summaries and recipient lookups. Programmatic read access is enabled per-partner — contact your account manager to have it turned on for your key, and they will confirm the exact endpoints and headers for your account.
3. SFTP / CSV data feed
If you prefer to deliver scheduled files rather than call the API, use the SFTP gateway. Your DMS or data team drops CSV files onto a dedicated endpoint and CarBuddy collects and processes them automatically — no per-row API calls.
- Connection details, key setup, and folder layout: SFTP Integration.
- Column format and quality rules: CSV Upload.
Column mapping
The importer maps your column headers to CarBuddy fields case-insensitively and accepts common aliases, so most DMS exports work without renaming columns. Representative aliases:
| CarBuddy field | Accepted headers (any case) |
|---|---|
first_name | first name, firstname, forename, first |
last_name | last name, lastname, surname, last |
email | email, email address, e-mail, email_address |
mobile | mobile, phone, tel, telephone, cell, phone number |
manufacturer | make, manufacturer, vehicle make |
vehicle | model, vehicle, vehicle model, car |
vehicle_reg | reg, registration, vrm, number plate, reg number |
dealer | dealer, dealership, branch, location |
assigned_branch | branch, assigned branch, location |
salutation | salutation, title, honorific |
opted_in_email | opted in email, email opt in, email consent |
opted_in_sms | opted in sms, sms opt in, sms consent |
Files may be comma-, tab-, or pipe-delimited — the delimiter is auto-detected. Raw DMS EVHC exports with dotted headers (e.g. Contacts.RegNo, Contacts.Salute) are recognised automatically. Health-check feeds may additionally carry Sale Outcome / RAG Status (or Outcome / Urgency) columns used for EVHC routing.
If a header isn't recognised it is ignored; contact your account manager to add a mapping.
4. Outbound webhooks & lead delivery
CarBuddy can push events to your systems as they happen — for example when a customer is classified as a qualified lead — so your CRM or DMS receives lead data without polling. Event types, payload format, and HMAC signature verification are documented on the API & Webhooks page.
DMS lead push (we integrate with your system)
Where a partner runs a lead-management system, CarBuddy can deliver qualified leads directly into it rather than (or as well as) firing a webhook. We already integrate outbound with lead-management platforms such as Dealerweb LMS and Cooper Solutions. If you operate a DMS/CRM you'd like CarBuddy to push leads into, contact your account manager with the endpoint and authentication details and we'll scope the connector.
5. Portal Data API
To pull your leads and conversations into your own CRM, BI, or data warehouse, use the Portal Data API.
GET https://portal.carbuddyai.com/api/leads
GET https://portal.carbuddyai.com/api/conversations
| Header | Value |
|---|---|
X-API-Key | Your cb_live_… portal key |
These endpoints return the same lead and conversation records visible in the portal — recipient details, message history, AI classifications, and conversation outcomes — filtered to your account. Ask your account manager to issue a portal API key and confirm the query parameters (date range, status filters, pagination) available for your integration.
For occasional exports without an integration, the portal also offers CSV export from the UI.
Interactive API reference
A live, machine-readable reference for the Campaign API is available:
- Swagger UI:
https://engine.carbuddyai.com/api/docs - OpenAPI spec (JSON):
https://engine.carbuddyai.com/api/openapi.json
You can import the OpenAPI spec into Postman, Insomnia, or your code generator of choice.
Consent & data protection
CarBuddy sends marketing communications under UK PECR/GDPR rules. You are responsible for ensuring every contact you enrol has a lawful basis for contact — the API enrols what you send it.
How the consent flags are evaluated at send time:
| Value you send | Behaviour |
|---|---|
true | Consented — we send on that channel. |
false | Blocked — we never send on that channel, for the life of the record. |
Omitted / null | Unknown — we send. Treated as legacy/soft opt-in data. |
An absent opted_in_sms / opted_in_email does not stop a send. This is deliberate — recurring DMS feeds rarely carry a consent column, and their operators strip non-consenting customers at source. If your feed can express non-consent, send an explicit false; if it cannot, exclude those contacts from the payload.
Regardless of the flags:
- Unsubscribes, STOP replies, hard bounces, and spam reports are honoured automatically and suppressed from all future campaigns for that client, not just the current one.
- Every outbound email carries an unsubscribe link; every SMS honours STOP.
- Contacts who complete repeated re-engagement cycles are permanently suppressed automatically.
See Data Privacy for how CarBuddy stores and processes customer data.
Getting connected
- Tell your CarBuddy account manager which method you want to use (API, SFTP, or both) and which direction (push, pull, or both).
- For the API, we issue you a per-client
cb_…key scoped to your client slug and campaign type(s). - For SFTP, we provision your account and folder and register your SSH key — see SFTP Integration.
- Test against a small batch, confirm the records appear in the portal, then go live.
Questions? Raise a ticket via the portal support system or contact your account manager.