Skip to main content

Overview

Cardinal Gray dispatches webhook notifications to your endpoint whenever a title entry undergoes a state change that matches your subscribed events. Webhooks are sent as POST requests with the full title entry as the JSON body.
To configure a webhook endpoint, contact the Cardinal Gray team. You’ll need to provide your endpoint URL and choose an authentication scheme.

Authentication

Cardinal Gray supports two outbound authentication schemes for webhook delivery:

Basic Auth

Authorization: Basic base64(username:password)
The Authorization header contains a Base64-encoded username:password pair. This is the recommended scheme for new integrations.

Bearer Token (Legacy)

Authorization: Bearer YOUR_TOKEN
x-partner-key: YOUR_PARTNER_KEY
Legacy integrations may receive a bearer token in the Authorization header and/or an x-partner-key header. New integrations should use Basic Auth.

Subscribable Events

EventFires When
title.job_status.completeEntry processing finishes successfully (job_status transitions to complete)
title.job_status.errorEntry processing fails terminally (job_status transitions to error)
title.data.foundNew enrichment data is discovered (NMVTIS, public portal, or private state pull transitions from not_foundfound)
title.data.not_foundReserved for future use
title.account_status.*Any account_status field change (wildcard — fires for all transitions)

Account Status Lifecycle

The title.account_status.* event fires with the specific new status appended. Possible values:
title.account_status.originated
title.account_status.poa_sent
title.account_status.poa_signed
title.account_status.filing_en_route
title.account_status.filing_received
title.account_status.lien_delay
title.account_status.lien_error
title.account_status.lien_filed
title.account_status.lien_perfected
title.account_status.account_paid
title.account_status.lien_release_pending
title.account_status.lien_release_complete

Payload Shape

The webhook payload is a POST request with Content-Type: application/json. The body is the full title entry (identical to GET /title/{id} response) plus a webhook_events array indicating which subscribed events triggered this dispatch.
Example Webhook Payload
{
  "entryId": "ffe3f543-cd92-4cb7-a78f-68a58b1fe8d3",
  "website": "yourorg.com",
  "VIN": "19UUA56602A000960",
  "state": "FL",
  "Borrower": "Jane Doe",
  "job_status": "complete",
  "account_status": "poa_signed",
  "account_data": {
    "vehicle": {
      "vin": "19UUA56602A000960",
      "year": "2002",
      "make": "ACURA",
      "model": "TL",
      "body_style": "SEDAN",
      "title": {
        "title_number": "123456789",
        "issuing_state": "FL",
        "issue_date": "2023-01-15",
        "odometer_reading": "98500",
        "odometer_status": "ACTUAL"
      },
      "owners": [
        {
          "name": { "first": "Jane", "middle": "M", "last": "Doe" },
          "address": {
            "street": "123 Main St",
            "city": "Miami",
            "state": "FL",
            "zip": "33101"
          }
        }
      ],
      "liens": [
        {
          "position": 1,
          "lienholder_name": "First National Bank",
          "date_filed": "2023-01-15"
        }
      ]
    },
    "loan": {
      "loan_amount": "25000",
      "borrower": [
        {
          "name": { "first": "Jane", "middle": "M", "last": "Doe" },
          "address": {
            "street": "123 Main St",
            "city": "Miami",
            "state": "FL",
            "zip": "33101"
          }
        }
      ],
      "lender": {
        "name": "Your Lending Co",
        "address": {
          "street": "456 Finance Ave",
          "city": "New York",
          "state": "NY",
          "zip": "10001"
        }
      }
    },
    "txn_quick_reference": "refi"
  },
  "nmvtis_found_status": "found",
  "nmvtis_pull": "https://s3-presigned-url...",
  "state_found_status": "found",
  "state_pull": "https://s3-presigned-url...",
  "signature_requests": [
    {
      "id": "NTRZ-abc123",
      "type": "RON",
      "status": "COMPLETED",
      "created_at": "2026-06-20T10:00:00Z",
      "updated_at": "2026-06-23T22:00:00Z",
      "signers": [
        { "name": { "first": "Jane", "last": "Doe" } }
      ],
      "documents_to_sign": [
        { "filename": "poa.pdf", "id": "doc-1", "signer_id": ["signer-1"] }
      ]
    }
  ],
  "fee_estimate": {
    "tax": { "taxable_amount": 25000, "total": 1750, "items": [] },
    "registration": { "total": 225, "items": [] },
    "title": { "total": 75, "items": [] },
    "submission_instructions": {
      "payable_to": "FL DMV",
      "address": { "street": "...", "city": "Tallahassee", "state": "FL", "zip": "32301" }
    }
  },
  "webhook_events": ["title.account_status.poa_signed"]
}

Key Fields

FieldTypeDescription
entryIdstringUnique identifier for the title entry
websitestringOrganization identifier
VINstringVehicle Identification Number
statestringTarget state for title processing
job_statusenumProcessing status: pending, input_parsing, enriching, generating_forms, complete, error
account_statusenumLifecycle status (see Account Status Lifecycle above)
account_dataobjectStructured vehicle, loan/sale, and owner data (see Core Ontology)
nmvtis_found_statusenumNMVTIS enrichment result: pending, found, not_found, error, unavailable, skipped
state_found_statusenumState/private enrichment result (same enum as above)
signature_requestsarraySigning ceremony status (DocuSign, Notarize, etc.)
fee_estimateobjectCalculated DMV fees (tax, registration, title)
webhook_eventsstring[]Which subscribed events triggered this webhook delivery
S3 document paths (nmvtis_pull, state_pull, form_* fields) are delivered as presigned URLs valid for 1 hour. Download or process them promptly.

Delivery Semantics

  • Method: POST
  • Content-Type: application/json
  • Retry: Exponential backoff on 5xx responses (up to 3 retries)
  • Timeout: 10 second response timeout per attempt
  • Idempotency: The same event may be delivered more than once. Use entryId + webhook_events to deduplicate.

Success / Failure

Your ResponseOur Behavior
2xxDelivery confirmed, no retry
4xxClient error logged, no retry (fix your endpoint)
5xxRetried with exponential backoff
TimeoutTreated as 5xx, retried

Testing

To trigger a test webhook:
  1. Create a title entry via POST /title with enrichment enabled (sync_nmvtis: true)
  2. Wait for job_status to reach complete — this fires title.job_status.complete and potentially title.data.found
  3. Update account_status via the dashboard or signing flow to trigger title.account_status.* events
You can verify your endpoint received the payload and responded with 2xx. Contact the Cardinal Gray team if you need help debugging delivery issues.