API Documentation

This area is for authorized partners only. Please enter your access code to continue.

Incorrect access code. Please try again.

Embedded Insurance API - Auto

The Embedded Insurance API is organized around REST. It accepts JSON request bodies, returns JSON responses, and uses standard HTTP response codes and Bearer token authentication.

Base URL https://api.embeddedinsurance.com
All requests must include Authorization: Bearer <access_token> and Content-Type: application/json unless otherwise noted.

Authentication

POST https://auth.embeddedinsurance.com/oauth2/token

The EI API uses OAuth 2.0 client credentials. Exchange your client_id and client_secret for a short-lived Bearer token, then include it in the Authorization header of every subsequent request.

Your credentials will be shared via a secure one-time link during partner onboarding.

Keep credentials private - never expose them in client-side code, Git repositories, or other publicly accessible locations.
Request Body (x-www-form-urlencoded)
FieldTypeDescription
client_id string required Your partner client ID
client_secret string required Your partner client secret
grant_type string required Always client_credentials
Response
200Returns access_token, token_type, and expires_in
401Invalid credentials
Request
POST https://auth.embeddedinsurance.com/oauth2/token
Content-Type: application/x-www-form-urlencoded

client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=client_credentials
Response
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5...",
  "token_type": "Bearer",
  "expires_in": 3600
}
Using the Token
Authorization: Bearer <access_token>

Embedded Component

The Embedded Component is a drop-in React widget that surfaces a personalized auto insurance offer directly inside your application - on a dashboard, account page, or post-purchase screen - without redirecting the customer to a hosted microsite.

Published as @ei-tech/embedded-component on npm. You give it a leadId and two async callbacks (getContent and getUrl) that proxy to your backend; the component handles polling, rendering, and CTA hand-off to the EI microsite.

Use the Embedded Component when you want to keep customers inside your app for the offer surface. Use Get Quote Link or Get Quote Share Link when you want to send them straight to the hosted quoting microsite instead.
How it works
  1. On mount, the component calls getContent(leadId), which hits a route on your backend (e.g. GET /api/embedded-content/:leadId).
  2. Your backend authenticates with EI via POST /oauth2/token and proxies GET /auto/v1/leads/:id/embedded-content.
  3. The component renders the layout returned (content, content-cta, image-content, image-content-cta, or none).
  4. If the response includes "continuePolling": true, the component schedules another getContent call after pollingInterval ms (default 5000), up to maxPollingAttempts (default 50).
  5. When the customer clicks the CTA button, the component calls getUrl(leadId) - your backend proxies POST /auto/v1/leads/:id/get-link - and opens the returned one-time URL in a new tab.

Your EI client credentials never leave your server - the browser only ever talks to your two proxy routes.

Embedded Component Your Backend EI API GET /api/auto-quote POST /oauth2/token access_token (Bearer) GET /auto/v1/leads/:id/ embedded-content content payload content payload Render offer If the response includes "continuePolling": true, the component re-runs getContent every pollingInterval ms (default 5s) until polling stops.
Component props
PropTypeDescription
leadIdstringrequiredThe EI lead ID returned by Create Lead
getContent(leadId) => Promise<Content>requiredAsync fetch of the content payload from your backend proxy
getUrl(leadId) => Promise<string>requiredAsync fetch of the one-time microsite URL when the customer clicks the CTA
theme'dark' | 'light'optionalVisual theme. Defaults to dark
pollingIntervalnumberoptionalMilliseconds between content polls. Defaults to 5000
maxPollingAttemptsnumberoptionalCap on poll iterations. Defaults to 50
Content payload

The shape returned by /embedded-content (passed through by your backend) determines what the component renders. layout selects the variant; the other fields are populated according to the variant's schema.

layoutRendersRequired fields
noneNothing-
contentHeading + subheading + footermainHeading, subHeading, footerText
content-ctaText with a CTA buttonAbove + buttonText
image-contentImage + textmainHeading, subHeading, footerText, imageUrl, imageAlt
image-content-ctaImage + text + CTAAll of the above + buttonText

Optional fields available on CTA layouts: ctaHeadline, buttonAriaLabel, buttonDisabled, buttonLoading, buttonBackgroundColor, buttonTextColor. All payloads accept continuePolling: boolean to drive the polling loop.

Install
npm install @ei-tech/embedded-component

React 18+ peer dependency. Import the bundled stylesheet once in your app entry: import '@ei-tech/embedded-component/styles';

1. Server-side proxy (two routes)
// Express example - keep this on your backend

async function getEIToken() {
  const r = await fetch('https://auth.embeddedinsurance.com/oauth2/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      client_id: process.env.EI_CLIENT_ID,
      client_secret: process.env.EI_CLIENT_SECRET,
      grant_type: 'client_credentials'
    })
  });
  return (await r.json()).access_token;
}

// Drives getContent - proxies the embedded-content payload
app.get('/api/embedded-content/:leadId', async (req, res) => {
  const token = await getEIToken();
  const r = await fetch(
    `https://api.embeddedinsurance.com/auto/v1/leads/${req.params.leadId}/embedded-content`,
    { headers: { Authorization: `Bearer ${token}` } }
  );
  res.json(await r.json());
});

// Drives getUrl - proxies the one-time microsite link
app.get('/api/quote-link/:leadId', async (req, res) => {
  const token = await getEIToken();
  const r = await fetch(
    `https://api.embeddedinsurance.com/auto/v1/leads/${req.params.leadId}/get-link`,
    {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ partnerBrand: process.env.EI_PARTNER_BRAND })
    }
  );
  const { url } = await r.json();
  res.json(url);
});
2. Render the component
import { EmbeddedInsurance, Content } from '@ei-tech/embedded-component';

const getContent = async (leadId: string): Promise<Content> => {
  const r = await fetch(`/api/embedded-content/${leadId}`);
  if (!r.ok) throw new Error('Failed to load content');
  return r.json();
};

const getUrl = async (leadId: string): Promise<string> => {
  const r = await fetch(`/api/quote-link/${leadId}`);
  if (!r.ok) throw new Error('Failed to get link');
  return r.json();
};

export function Dashboard({ leadId }: { leadId: string }) {
  return (
    <EmbeddedInsurance
      leadId={leadId}
      getContent={getContent}
      getUrl={getUrl}
      theme="dark"
    />
  );
}
Example content payload
{
  "layout": "image-content-cta",
  "mainHeading": "Your Quote is Ready!",
  "subHeading": "Click to view your personalized insurance details.",
  "buttonText": "View Now",
  "imageUrl": "https://cdn.example.com/quote.svg",
  "imageAlt": "Insurance Quote",
  "footerText": "Insurance by Embedded Insurance Agency, LLC.",
  "continuePolling": false
}

Create Lead

POST /auto/v1/leads

Send a customer's information to EI to get an auto insurance quote. At minimum you need the primary applicant's contact details, address, and one vehicle.

Pass "isTest": true at the root of the request body when working in a non-production context. The same endpoint and credentials work in both environments.
Applicant (required)
FieldTypeDescription
firstNamestringrequired
lastNamestringrequired
dateOfBirthstringrequiredFormat: YYYY-MM-DD
addressobjectrequiredaddress1, city, state (2-letter), zip (5-digit). address2 optional.
phoneNumberstringrequiredE.164 format: +1XXXXXXXXXX
emailstringrequiredMust be unique per lead
genderstringoptionalMale · Female · Non-Binary
maritalStatusstringoptionalSingle · Married · Divorced · Widowed · Separated · Domestic Partner
residenceOwnershipTypestringoptionalOwn · Rent · Other
monthsAtAddressintegeroptional
priorAddressobjectoptionalSame structure as address
licenseNumberstringoptional
licenseStatestringoptional2-letter state abbreviation
yearsLicensedintegeroptional
educationLevelstringoptionalHighSchool · BachelorsDegree · MastersDegree · and more
incomearrayoptionalArray of income objects: employmentType, employerName, jobTitle, monthsAtEmployer, annualIncome
Co-applicants (optional)

Object with numeric string keys "1""9". Each shares the same optional fields as applicant, plus:

FieldTypeDescription
relationshipToApplicantstringoptionalSpouse · Parent · Child · Relative · Cohabitant · Other
Vehicles (required - at least one)

Object with numeric string keys "1""9". Vehicle 1 is required.

FieldTypeDescription
makestringrequired
modelstringrequired
yearstringrequired4-digit year as string
vinstringoptional17-character VIN
trimstringoptional
estimatedAnnualMileageintegeroptional
isFinancedbooleanoptional
lienobjectoptionallienHolder, monthlyPayment, originalAmount, payoffAmount, remainingTerm
Root fields
FieldTypeDescription
orgIdstringrequiredYour organization ID provided by EI
isTestbooleanoptionalSet true for test requests
partnerExternalIdstringoptionalYour internal reference ID for this lead
partnerDataobjectoptionalArbitrary key-value metadata to pass through
Response
200Lead created successfully. Returns lead object with id.
400Validation error or duplicate lead
401Missing or invalid Bearer token
Request
POST /auto/v1/leads
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "applicant": {
    "firstName": "John",
    "lastName": "Doe",
    "dateOfBirth": "1980-01-15",
    "address": {
      "address1": "123 Main St",
      "city": "Boston",
      "state": "MA",
      "zip": "02108"
    },
    "phoneNumber": "+16175551234",
    "email": "john.doe@example.com",
    "gender": "Male",
    "maritalStatus": "Married"
  },
  "coapplicants": {
    "1": {
      "firstName": "Jane",
      "lastName": "Doe",
      "dateOfBirth": "1982-06-20",
      "relationshipToApplicant": "Spouse"
    }
  },
  "vehicles": {
    "1": {
      "vin": "1HGCM82633A123456",
      "make": "Toyota",
      "model": "Camry",
      "year": "2020"
    }
  },
  "orgId": "your-org-id"
}
Response
{
  "id": "bea82fae-e1b7-5bc5-810b-c38694e66aef",
  "status": "PENDING"
}

Get Lead

GET /auto/v1/leads/:id

Retrieve the latest status and quote information for a lead.

Path Parameters
FieldTypeDescription
idstring (UUID)requiredThe lead ID returned by Create Lead
Response
200Lead object with current status and available quotes
404Lead not found
Request
GET /auto/v1/leads/bea82fae-e1b7-5bc5-810b-c38694e66aef
Authorization: Bearer <access_token>

Update Lead

POST /auto/v1/leads/:id

Requote a lead with updated applicant, driver, or vehicle information. Only the fields included in the request body will be updated.

Path Parameters
FieldType
idstring (UUID)required
Request Body
FieldTypeDescription
idstring (UUID)requiredLead ID (must match path param)
addressobjectoptionalUpdated address
driversobjectoptionalKeyed "1""9", updated driver info
vehiclesobjectoptionalKeyed "1""9", updated vehicle info
Response
200Updated lead with refreshed quotes
400Validation error
Request
POST /auto/v1/leads/bea82fae-e1b7-5bc5-810b-c38694e66aef
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "id": "bea82fae-e1b7-5bc5-810b-c38694e66aef",
  "address": {
    "address1": "456 New Ave",
    "city": "Boston",
    "state": "MA",
    "zip": "02109"
  },
  "vehicles": {
    "1": {
      "vin": "1HGCM82633A123456",
      "make": "Toyota",
      "model": "Camry",
      "year": "2020"
    }
  }
}

Get Quote Content

GET /auto/v1/leads/:id/embedded-content

Returns the props needed to render the @ei-tech/embedded-component React component directly within your application. Use this endpoint when embedding the EI quoting experience inline rather than redirecting to a hosted microsite.

Path Parameters
FieldType
idstring (UUID)required
Response
200Component props object for @ei-tech/embedded-component
Request
GET /auto/v1/leads/bea82fae-e1b7-5bc5-810b-c38694e66aef/embedded-content
Authorization: Bearer <access_token>

Create Lead Event

POST /auto/v1/leads/:id/events

Record a lifecycle event against a lead. Use this to signal partner-side state changes that EI should be aware of.

Path Parameters
FieldType
idstring (UUID)required
Request Body
FieldTypeDescription
type string required Event type. Supported values:
APPLICANT_AUTHENTICATED
Request
POST /auto/v1/leads/bea82fae-e1b7-5bc5-810b-c38694e66aef/events
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "type": "APPLICANT_AUTHENTICATED"
}
Response
{
  "ok": true,
  "eventId": "evt_123456789"
}

Common Errors

These error patterns are returned by most EI API endpoints.

400Validation error or malformed request
401Missing or invalid Bearer token
403Unauthorized or client credentials not allowed
404Resource not found
500Server error or temporary outage

Most error responses include a JSON body with error and optionally message to explain the failure.

Example Error
{
  "error": "invalid_request",
  "message": "Missing required field: applicant.firstName"
}

Webhooks - Overview

EI delivers lifecycle events to a HTTPS URL you provide during onboarding. Each event arrives as an HTTP POST with a JSON body and is signed so you can verify it came from EI.

Headers (every event)
HeaderValue
Content-Typeapplication/json
X-Webhook-SignatureHex HMAC-SHA256 of the raw request body using your shared webhook secret - see Verifying Signatures
Common envelope

All event bodies share these fields:

FieldTypeDescription
idstringUnique event ID
leadIdstringThe lead this event relates to
partnerCodestringYour EI partner code
partnerExternalIdstringOptional - the ID you supplied via Create Lead
eventTypestringOne of verification · quote · lead_summary · needs_insurance
eventTimestringISO 8601 timestamp
idempotencyKeystringStable per unique event content - use it to deduplicate retries
Respond with 2xx within a few seconds to acknowledge receipt. Non-2xx responses or timeouts may be retried; treat your handler as idempotent by keying on idempotencyKey.
Minimal handler
// Express - keep the raw body so the signature check works
app.post('/webhooks/ei',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const sig  = req.headers['x-webhook-signature'];
    const body = req.body.toString('utf8');

    if (!verifyWebhookSignature(process.env.EI_WEBHOOK_SECRET, sig, body)) {
      return res.status(401).end();
    }

    const event = JSON.parse(body);
    // dedupe on event.idempotencyKey, then handle by event.eventType
    res.sendStatus(200);
  }
);

Verifying Signatures

Every webhook is signed with HMAC-SHA256 over the raw request body using a secret shared with you during onboarding. Verify the signature before trusting the payload.

  1. Read the X-Webhook-Signature header.
  2. Compute HMAC-SHA256(secret, rawBody) as a hex string.
  3. Compare the two using a constant-time equality check.
Use the raw request body - re-serializing parsed JSON will change byte ordering and break the check.
Node.js
import crypto from 'node:crypto';

const createWebhookSignature = (secret, body) => {
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(body);
  return hmac.digest('hex');
};

export const verifyWebhookSignature = (secret, signature, body) => {
  if (!signature) return false;
  const expected = createWebhookSignature(secret, body);
  try {
    return crypto.timingSafeEqual(
      Buffer.from(signature, 'hex'),
      Buffer.from(expected,  'hex'),
    );
  } catch {
    return false;
  }
};

Verification Events

POST eventType: verification

Delivered when insurance verification finishes for a lead - either successfully or with a failure reason.

Status values
completed failed
Completed - fields
FieldTypeDescription
insuranceVerification.idstringVerification record ID
insuranceVerification.sourcestringid-card · third-party
policyInfo.carrierstringVerified carrier name (optional)
policyInfo.policyTypestringAlways auto
policyInfo.policyNumberstringOptional
policyInfo.vehicles[]arrayvin, year, make, model - all optional
policyInfo.namedInsureds[]arrayfirstName, lastName, isPrimary
media[]arraydocumentType (insurance-id-card · declarations), url, description, contentType, size, createdAt, expiresAt
verificationConfidencenumberOptional - confidence score from 0.00 to 1.00
Failed - failure reasons
_tagDescription
NoActiveAutoPoliciesFoundNo active auto policies were found for the insured
NoVehicleMatchesFoundNo auto policies with matching vehicles were found
RetrieveErrorAn error occurred while retrieving verification data

Media URLs are pre-signed and expire - download or copy assets before expiresAt if you need to retain them.

Completed
{
  "id": "evt_abc123",
  "leadId": "lead_987654321",
  "partnerExternalId": "partner_app_456",
  "partnerCode": "ACME",
  "eventType": "verification",
  "eventTime": "2024-01-15T10:30:00.000Z",
  "status": "completed",
  "idempotencyKey": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "insuranceVerification": {
    "id": "verification_123",
    "source": "id-card",
    "policyInfo": {
      "carrier": "Progressive",
      "policyType": "auto",
      "policyNumber": "POL123456789",
      "vehicles": [
        { "vin": "1HGBH41JXMN109186", "year": "2023", "make": "Honda", "model": "Accord" }
      ],
      "namedInsureds": [
        { "firstName": "Jane", "lastName": "Doe", "isPrimary": true }
      ]
    },
    "media": [
      {
        "documentType": "insurance-id-card",
        "url": "https://storage.googleapis.com/ei-media/insurance-cards/id-card-123.jpg",
        "description": "Insurance identification card",
        "contentType": "image/jpeg",
        "size": 512000,
        "createdAt": "2024-01-15T10:25:00.000Z",
        "expiresAt": "2024-01-22T10:25:00.000Z"
      }
    ],
    "verificationConfidence": 0.95
  }
}
Failed
{
  "id": "evt_def456",
  "leadId": "lead_987654321",
  "partnerCode": "ACME",
  "eventType": "verification",
  "eventTime": "2024-01-15T10:35:00.000Z",
  "status": "failed",
  "idempotencyKey": "f6e5d4c3-b2a1-0987-fedc-ba9876543210",
  "insuranceVerification": {
    "id": "verification_124",
    "source": "third-party",
    "failureReasons": [
      { "_tag": "NoActiveAutoPoliciesFound", "message": "No active auto policies found" }
    ]
  }
}

Quote Events

POST eventType: quote · status: completed

Delivered when a quote is successfully generated for a lead.

Fields
FieldTypeDescription
quote.idstringQuote ID
quote.carrierstringInsurance carrier the quote is with
quote.totalPremiumCentsintegerTotal premium in cents (optional)
quote.savingsAmountCentsintegerSavings vs current policy in cents
quote.savingsMonthlyCentsintegerMonthly savings in cents
quote.savingsAnnualCentsintegerAnnual savings in cents (rounded to nearest $10)
quote.currentPaymentMonthlyCentsintegerCurrent monthly payment in cents
quote.newPaymentMonthlyCentsintegerNew monthly payment in cents

Savings and payment fields are populated only when the lead has both a quote and prior insurance information from verification. Expect them to be absent for cold quotes.

With prior insurance
{
  "id": "evt_ghi789",
  "leadId": "lead_987654321",
  "partnerExternalId": "partner_app_456",
  "partnerCode": "ACME",
  "eventType": "quote",
  "eventTime": "2024-01-15T11:15:00.000Z",
  "status": "completed",
  "idempotencyKey": "12345678-abcd-ef01-2345-6789abcdef01",
  "quote": {
    "id": "quote_456",
    "carrier": "Geico",
    "totalPremiumCents": 120000,
    "savingsAmountCents": 30000,
    "savingsMonthlyCents": 2500,
    "savingsAnnualCents": 30000,
    "currentPaymentMonthlyCents": 12500,
    "newPaymentMonthlyCents": 10000
  }
}
Cold quote
{
  "id": "evt_jkl012",
  "leadId": "lead_987654321",
  "partnerCode": "ACME",
  "eventType": "quote",
  "eventTime": "2024-01-15T11:15:00.000Z",
  "status": "completed",
  "idempotencyKey": "abcdef01-2345-6789-abcd-ef0123456789",
  "quote": {
    "id": "quote_457",
    "carrier": "Allstate",
    "totalPremiumCents": 150000
  }
}

Lead Summary Events

POST eventType: lead_summary

A consolidated lifecycle stream covering verification, quoting, viewing, and binding for a lead. Each event carries a summary object with whichever components are available at that point in the journey.

Status values
StatusRequired summary keysMeaning
verification.completedinsuranceVerificationVerification finished successfully
quote.completedquote (+ optional insuranceVerification)A quote was generated
quote.viewedquoteThe lead viewed a quote
policy.boundpolicyThe lead bound a policy
error-Lead is in an error state (e.g. quoting error)
summary.insuranceVerification
FieldTypeDescription
idstring
statusstringpending · completed · failed
sourcestringid-card · third-party
policyInfoobjectSame shape as in Verification Events
media[]arraySame shape as in Verification Events
verifiedAtstringISO 8601 timestamp
summary.quote
FieldTypeDescription
idstring
statusstringcompleted · viewed
carrierstring
totalPremiumCentsinteger
savingsAmountCentsintegerOptional
createdAtstringISO 8601 timestamp
viewedAtstringOptional, present on quote.viewed
summary.policy
FieldTypeDescription
idstring
carrierstring
boundAtstringISO 8601 timestamp
quote.completed
{
  "id": "req_123456789",
  "leadId": "lead_987654321",
  "partnerExternalId": "partner_app_456",
  "eventType": "lead_summary",
  "eventTime": "2024-01-15T11:15:00.000Z",
  "status": "quote.completed",
  "summary": {
    "insuranceVerification": {
      "id": "verification_123",
      "status": "completed",
      "source": "id-card",
      "policyInfo": { "carrier": "Progressive", "policyType": "auto" },
      "verifiedAt": "2024-01-15T10:30:00.000Z"
    },
    "quote": {
      "id": "quote_456",
      "status": "completed",
      "carrier": "Geico",
      "totalPremiumCents": 120000,
      "savingsAmountCents": 30000,
      "createdAt": "2024-01-15T11:15:00.000Z"
    }
  }
}
quote.viewed
{
  "id": "req_123456789",
  "leadId": "lead_987654321",
  "partnerExternalId": "partner_app_456",
  "eventType": "lead_summary",
  "eventTime": "2024-01-15T11:30:00.000Z",
  "status": "quote.viewed",
  "summary": {
    "quote": {
      "id": "quote_456",
      "status": "viewed",
      "carrier": "Geico",
      "totalPremiumCents": 120000,
      "createdAt": "2024-01-15T11:15:00.000Z",
      "viewedAt": "2024-01-15T11:30:00.000Z"
    }
  }
}
policy.bound
{
  "id": "req_123456789",
  "leadId": "lead_987654321",
  "partnerExternalId": "partner_app_456",
  "eventType": "lead_summary",
  "eventTime": "2024-01-15T12:00:00.000Z",
  "status": "policy.bound",
  "summary": {
    "policy": {
      "id": "policy_789",
      "carrier": "Geico",
      "boundAt": "2024-01-15T12:00:00.000Z"
    }
  }
}
error
{
  "id": "req_123456789",
  "leadId": "lead_987654321",
  "partnerExternalId": "partner_app_456",
  "eventType": "lead_summary",
  "eventTime": "2024-01-15T11:45:00.000Z",
  "status": "error",
  "summary": {}
}

Needs Insurance Event

POST eventType: needs_insurance

Delivered when a user expresses interest in finding insurance via the insurance verification app. Use this signal to route the lead into a quoting flow.

Fields
FieldTypeDescription
sourcestringAlways insurance_verification_app

All other fields come from the common envelope.

Event
{
  "id": "evt_mno345",
  "leadId": "lead_987654321",
  "partnerExternalId": "partner_app_456",
  "partnerCode": "ACME",
  "eventType": "needs_insurance",
  "source": "insurance_verification_app",
  "eventTime": "2024-01-15T09:00:00.000Z",
  "idempotencyKey": "11112222-3333-4444-5555-666677778888"
}

Get Health

GET /auto/v1/health

Check the operational status of the API. No authentication required. Use this for uptime monitoring or pre-flight checks.

Response
200API is healthy
5xxService degraded or unavailable
Request
GET https://api.embeddedinsurance.com/auto/v1/health
Response
{
  "status": "ok"
}