---
name: codriver-integration
description: Integrate a CRM, DMS, dealer website or lead tool with AutoUncle CoDriver, AutoUncle's AI lead follow-up for car dealers. Use when asked to send leads to AutoUncle CoDriver, read AutoUncle CoDriver opportunities or appointments, receive AutoUncle CoDriver webhooks, or build or test a AutoUncle CoDriver integration end to end.
---

# Integrate a system with AutoUncle CoDriver

AutoUncle CoDriver follows up on a car dealer's leads. You are connecting the user's system (a CRM, a DMS, a website, an agency or lead tool) to one dealer's AutoUncle CoDriver organization. Everything is standards-based: OAuth 2.1 client credentials, an OpenAPI 3.1 contract, RFC 9457 errors, CloudEvents delivered as Standard Webhooks.

**Source of truth:** the OpenAPI contract at https://codriver.autouncle.com/openapi.yaml (fetch it; it describes every field and every event) and the guide at https://codriver.autouncle.com/developers (also as plain text: https://codriver.autouncle.com/developers/llms.txt). When this skill and the contract disagree, the contract wins.

## 1. Agree the scope with the user

Ask, and write the answers down before coding:

- **Direction.** Push leads into AutoUncle CoDriver? Get updates back (opportunity status, appointments, messages, won/lost)? Both?
- **Delivery of updates.** Can the user's system receive HTTPS webhooks? If not, poll the events feed.
- **Their record.** Which object in their system is "a lead" or "an inquiry", and what is its stable ID? That becomes `external_reference`.
- **Who has AutoUncle CoDriver access.** An owner or admin of the dealer's AutoUncle CoDriver organization must create the credentials (step 2). You never create credentials yourself.

## 2. Credentials and a test setup (done by the user, in AutoUncle CoDriver)

Ask the user to do this under **Settings** in AutoUncle CoDriver and give you the results through a secrets manager or environment variables, never in chat or source code:

0. Work in a **sandbox organization** (the user asks their AutoUncle contact for one): it is in safe mode, so nothing you trigger reaches a customer, a CRM or a sales rep. A test lead is only a label, processed in full.
1. **Lead sources → Create lead source**, type *API* → the lead source ID `src_…`.
2. **Developers → Create application** → preset *Two-way integration*, tick **Test client** → `CLIENT_ID`, `CLIENT_SECRET`.
3. If they receive webhooks: **Developers → Webhook endpoints → Add endpoint** with the HTTPS URL you will build, and the event types → the signing secret `whsec_…`.

Configure these as `CODRIVER_CLIENT_ID`, `CODRIVER_CLIENT_SECRET`, `CODRIVER_LEAD_SOURCE_ID`, `CODRIVER_WEBHOOK_SECRET` and base URL `https://codriver.autouncle.com`.

## 3. Authenticate (`oauthToken`)

`POST /oauth/token` with HTTP Basic `CLIENT_ID:CLIENT_SECRET` and `grant_type=client_credentials&scope=leads_write leads_read opportunities_read events_read` (only the scopes you need). Cache the JWT for its `expires_in` (48 h); get a new one on `401 invalid_token`. Scopes: `leads_write`, `leads_read`, `opportunities_read`, `events_read`.

## 4. Map fields

Fetch the `LeadCreateRequest` schema from the contract and make a mapping table with the user: their field → AutoUncle CoDriver field → transformation. Rules:

- `lead_source_id` (required), and `email` or `phone` (at least one; `email: null` for phone-only).
- The customer's own words go in `message`; structured facts in `customer`, `desired_vehicles`, `trade_in_vehicles`, `budget`, `appointment`. Don't invent values; leave out what you don't have.
- `external_reference`: `{ "system": "<stable name of their system>", "id": "<their record ID>", "url": "<optional link>" }`.
- Up to 20 flat `metadata` keys for campaign IDs and the like, not for prose.
- Timestamps RFC 3339 UTC; IDs from AutoUncle CoDriver are public IDs with prefixes (`led_`, `opp_`, `cus_`, `apt_`, `evt_`); store them as strings.

## 5. Push leads (`createLead`)

`POST /api/v1/leads` with:

- a new UUID `Idempotency-Key` per lead, **reused on every retry of that lead**;
- `external_reference` on every lead.

Handle the answer:

- `202`: store `lead_id` and `correlation_id` on their record.
- `200` with `duplicate: true`: the record was already sent; store the returned `lead_id`. Not an error.
- `warnings`: log them; they are fields AutoUncle CoDriver ignored. Fix the mapping.
- `409 idempotency_key_in_progress`: wait `Retry-After`, retry with the same key.
- `429 rate_limited`: wait `Retry-After`. `5xx` or a network error: retry with exponential backoff and the same key.
- Any other `4xx`: don't retry unchanged. Read `code` and see https://codriver.autouncle.com/developers/errors/<code>.

Trade-in photos or fields that arrive after the lead (`createTradeInUpdate`, `createTradeInPhotos`) use the lead's `correlation_id`.

## 6. Get updates back

**Webhooks (preferred).** Build an HTTPS endpoint that:

1. reads the **raw** body;
2. verifies it with a Standard Webhooks library (`standardwebhooks` on npm and PyPI, and libraries for Ruby, Go, PHP, Java and C#) using `CODRIVER_WEBHOOK_SECRET`; a failed verification answers `400`;
3. dedupes on `webhook-id` (the event `id`): delivery is at least once; retries can reorder events and IDs don't give the order, so before overwriting a record it re-reads the resource with `GET`;
4. answers `2xx` within 15 seconds and does the work in a background job;
5. switches on `type` and ignores types it doesn't handle.

Event types: `lead.received`, `lead.processed`, `opportunity.created`, `opportunity.updated`, `opportunity.assigned`, `opportunity.closed`, `opportunity.reopened`, `message.received`, `message.sent`, `appointment.requested`, `appointment.booked`, `appointment.rescheduled`, `appointment.confirmed`, `appointment.cancelled`. Each event's `data` has a JSON Schema at its `dataschema` URL. Use `data.opportunity.external_references` to find the user's record. Events with `"test": true` are test data.

**Events feed (no webhooks).** `listEvents`: `GET /api/v1/events?after=<cursor>&limit=100` every minute; persist `next_cursor` after processing each page; handle events exactly as above.

**Reading on demand.** `getLead` (`GET /api/v1/leads/{id}`: processing status), `getOpportunity`, `listOpportunities` (`external_reference_system` + `external_reference_id` to find the opportunity for their record; `updated_since` for a periodic sync; cursor pagination via `next_cursor`), `listOpportunityAppointments`.

## 7. Verify before go-live

With the Test client:

1. Push a test lead and poll `getLead` until `status` is `processed`.
2. Retry the same push with the same `Idempotency-Key`: the response repeats and nothing new is created.
3. Push it again with a new key but the same `external_reference`: `200 duplicate`.
4. In AutoUncle CoDriver, on the webhook endpoint's page, **Send a test event** for each type you handle: each must be accepted (`2xx`). Send a tampered body to your own endpoint locally: it must answer `400`.
5. Show the user the delivery log on that page.

Then the user switches to a live client (a new client with *Test client* unticked) and watches the first real leads with the dealer.

## Don'ts

- Don't put secrets in code, logs, URLs or chat.
- Don't parse the webhook body before verifying it, and don't skip verification.
- Don't send customer data for anything but this dealer's own leads.
- Don't rely on undocumented fields; the contract is additive, so ignore fields you don't know.
