Quotes API
One POST prices a shopper for Just Pay-Per-Mile and Just Unlimited. Each quote comes back with a price, payment plans and a link that takes the shopper to just.insure to buy. A product Just can't offer comes back as a decline, with a code you can branch on.
How it fits together
- Your server calls
POST /v1/quoteswith the shopper, any other drivers, the vehicle and the Just package you want priced. - Just answers 200 with
quotes[]for the products it can offer anddeclines[]for the rest. Either list can be empty. - You show the prices. The shopper clicks a quote's
clickToBuyUrl, lands on just.insure with that quote open, and buys there.
POST /v1/quotes # every live product, one callRC1 is indicative; the final price comes later. An RC1 quote is priced from what you send. Just runs its driving-history and credit checks on just.insure before the shopper buys, When the shopper's answers are accurate, the final price should be very close to the RC1 quote; differences come from the checks finding something the request didn't include.
Quick start#
Send a JSON body with your key in the x-api-key header. The example asks for BASIC_FULL_COVER for one Arizona driver and one vehicle, identified by a partial VIN.
- Get your staging key from your Just partnership contact.
- Copy the request on the right, in curl, Node or Python.
- Check the response: one entry in
quotesper product Just can offer, each with aprice,paymentPlansand aclickToBuyUrl. Anything Just can't offer is indeclines. See the quote object for every field, and errors if the call fails.
Environments#
Use staging to build and test. Every production call that reaches pricing creates a real quote at Just, and a customer record for an email Just hasn't seen before, so only send real shoppers there.
| Environment | Base URL | Use for |
|---|---|---|
| Staging | | Integration and testing. Prices are realistic but not binding. |
| Production | | Live shoppers only. |
| Property | Value |
|---|---|
| Methods | POST /v1/quotes only. Requests are application/json; a 200 is application/json and an error is application/problem+json. |
| Latency and timeout | A typical call takes around 300 ms (p90). Still set a client timeout; 30 seconds is the upper bound. In the rare case pricing takes too long, Just answers 504 dependency-timeout, which is safe to retry. |
| Body size | Up to 64 KiB. Up to 9 additional drivers, 10 vehicles and 50 events in each history list. |
| Rate limits | None enforced. |
| Idempotency | Send an Idempotency-Key header on every call: a unique value per quote attempt, a V4 UUID is recommended, up to 255 characters. Reuse the same key when you retry that attempt. In v1 Just records the key but does not deduplicate yet: every call that reaches pricing creates new quotes, each with a new id and clickToBuyUrl, so use the newest response. A later release will replay the first response for a repeated key within 24 hours; sending the key now means your retries work unchanged when that ships. A retry doesn't duplicate the shopper meanwhile: Just reuses the customer with the same email. Retry only on network failures and 5xx. |
| Support | Send Just the Request-Id response header of the call, whatever its status, and the quote's id for a question about a quote. |
Authentication#
Send your API key on every request in the x-api-key header. Just issues one key per partner for staging and one for production. Keys don't expire; ask Just to rotate one if it leaks.
The key is your identity. Just attributes every quote to the partner the key belongs to, and nothing in the request body can change that.
| Status | When | Body |
|---|---|---|
| 401 | The key is missing or isn't a Just key. Rejected by Just's API gateway. | The gateway's own JSON, not a problem. |
| 403 | The key is a Just key but isn't enabled for this API, or your access is paused. Both cases get the same answer. | application/problem+json, type forbidden. |
Keep keys on your servers; never call the API from a browser or an app.
Request headers#
| Header | Value | |
|---|---|---|
x-api-key | Required | Your API key for the environment. |
Content-Type | Required | application/json. Anything else is a 415. |
Idempotency-Key | Optional | A unique value per quote attempt, up to 255 characters; a V4 UUID is recommended. Reuse it when you retry that attempt; see idempotency. A longer key is a 400 INVALID_LENGTH at path Idempotency-Key. |
POST /v1/quotes HTTP/1.1
Host:
Content-Type: application/json
x-api-key:
Idempotency-Key: 5f2b8c1e-7d3a-4e9b-a6c2-0f1d8e7b3a94{
"code": 401,
"message": "UNAUTHENTICATED: Method doesn't allow unregistered callers (callers without established identity). Please use API Key or other form of API consumer identity to call this API."
}
{
"type": "https://docs.just.insure/quotes/errors#forbidden",
"title": "Forbidden",
"status": 403,
"detail": "This API key is not enabled for this API.",
"requestId": "req_01M504XP9WG7KYHRJXJG7DJ13N"
}
Request IDs#
Every response carries a Request-Id header that Just generates for the call: req_ followed by a 26-character ULID, for example req_01M504WQC04TFF59TDWH9EDD1R. It is on every 200, 4xx and 5xx from the API. The gateway's 401 is the one exception: it is answered before the request reaches Just's API.
Log it with every call, whatever the status. It is the id Just finds a call by, so send it with any support question, together with the quote's id when the question is about a quote.
requestId, the same value as the header, so a stored error can still be traced.HTTP/1.1 200 OK
Content-Type: application/json
Request-Id: req_01M504WQC04TFF59TDWH9EDD1RHTTP/1.1 502 Bad Gateway
Content-Type: application/problem+json
Request-Id: req_01M504X6TYH4QX4FR84G98PBSK
{
"type": "https://docs.just.insure/quotes/errors#dependency-failure",
"title": "Bad Gateway",
"status": 502,
"detail": "A service Just depends on failed. It is safe to retry.",
"requestId": "req_01M504X6TYH4QX4FR84G98PBSK"
}Testing#
Test on staging. Start from the quick start request and use the request builder below to try each outcome. Every quote you get back is an RC1 quote; see how RC1 quotes work. Please don't send test traffic to production; it creates real customer records.
Just emails the shopper only when you send notifyShopper: true, on staging as in production. Use an inbox you control to see that email. Addresses at example.com are never emailed.
Test emails
The email decides how clickToBuyUrl signs in (see clickToBuyUrl sign-in), so pick it for what you want to see:
| What you want to test | Which email to send |
|---|---|
One-click sign-in. The clickToBuyUrl signs the shopper straight in to just.insure with the quote open. | An address Just has never seen, so use a new one every run: shopper+run-001@example.com on the first run, shopper+run-002@example.com on the next, and so on. |
Sign-in required. The clickToBuyUrl opens just.insure and asks the shopper to sign in by email first, then shows the quote. This is what a returning shopper gets. | An address you've already sent in an earlier run, for example shopper+run-001@example.com again. |
| Just's quote email. Just emails the shopper the quote. | An inbox you can read, with a new tag each run, and notifyShopper: true in the request: for example yourname+jpq-001@yourcompany.com. |
Addresses at example.com are never emailed, so they're safe for repeat runs.
Addresses that quote
| state | line1 | city | zipCode |
|---|---|---|---|
| AZ | 302 W Almeria Rd | Phoenix | 85003 |
| NV | 123 Main St | Las Vegas | 89101 |
| IN | 789 Main St | Indianapolis | 46204 |
Vehicles
| Send as | Value | Vehicle |
|---|---|---|
vin | 1GC0K9CG0BF213909 | 2011 Chevrolet Silverado |
partialVin | 19XFA1F5*A | 2010 Honda Civic |
Request builder
Pick a scenario and the request on the right updates, with the answer Just gives. A 400 lists every problem at once. Declines that need no pricing stop at the first that applies, in the order in eligibility.
Products and states#
By default every call prices both products, Pay-Per-Mile first. Send products to price only some of them, in your order. Both are 90-day terms that renew; the rate at renewal reflects how safely the customer drives.
| Product | product | How the customer pays | Payment plans returned |
|---|---|---|---|
| Just Pay-Per-Mile | PAY_PER_MILE | A daily rate plus a rate per mile driven. | Every 14 days |
| Just Unlimited | UNLIMITED | A fixed daily rate, unlimited miles. | Every 14 days (default) or every 30 days |
The state comes from policyholder.address.state, and Just also checks that it covers policyholder.address.zipCode.
| State | Status |
|---|---|
Arizona AZ | Live |
Nevada NV | Live |
Indiana IN | Live |
| Any other state | 200 with a UNSUPPORTED_STATE decline for every product. No record is created. New states are announced in the changelog. |
Packages#
Just sells three packages per state, and you choose one with package. Coverages can't be mixed and matched, and Just doesn't adjust the package to limits you send; each quote lists what it covers in package.coverages. Limits below are US dollars.
| Arizona | MINIMUM_LIABILITY | BASIC_FULL_COVER | REGULAR_FULL_COVER |
|---|---|---|---|
| Bodily Injury | 25,000 / 50,000 | 25,000 / 50,000 | 50,000 / 100,000 |
| Property Damage | 15,000 | 15,000 | 50,000 |
| Collision and Comprehensive | Not included | 1,000 deductible | 500 deductible |
| Glass | Not included | Included | Included |
| Uninsured / Underinsured Motorist BI | Not in the RC1 quote. The customer can add it on just.insure. | ||
| Nevada | MINIMUM_LIABILITY | BASIC_FULL_COVER | REGULAR_FULL_COVER |
|---|---|---|---|
| Bodily Injury | 25,000 / 50,000 | 25,000 / 50,000 | 50,000 / 100,000 |
| Property Damage | 20,000 | 20,000 | 50,000 |
| Collision and Comprehensive | Not included | 1,000 deductible | 500 deductible |
| Uninsured / Underinsured Motorist BI | 25,000 / 50,000 | 25,000 / 50,000 | 50,000 / 100,000 |
| Medical Payments | 1,000 per person | 1,000 per person | 1,000 per person |
| Indiana | MINIMUM_LIABILITY | BASIC_FULL_COVER | REGULAR_FULL_COVER |
|---|---|---|---|
| Bodily Injury | 25,000 / 50,000 | 25,000 / 50,000 | 50,000 / 100,000 |
| Property Damage | 25,000 | 25,000 | 50,000 |
| Collision and Comprehensive | Not included | 1,000 deductible | 500 deductible |
| Uninsured Motorist BI | 25,000 / 50,000 | 25,000 / 50,000 | 50,000 / 100,000 |
| Underinsured Motorist BI | 50,000 / 100,000 | 50,000 / 100,000 | 50,000 / 100,000 |
| Uninsured Motorist Property Damage | 25,000, no deductible | 25,000, no deductible | 50,000, no deductible |
Bodily Injury is per person / per accident. Property Damage is per accident. The tables show Just's current packages; always display what each quote's package.coverages says, which is what the shopper buys.
Package mapping guide#
Most partners sell tiers of their own. Map each tier to one Just package once, in your integration, using its shape:
| Your tier | Send package |
|---|---|
| Liability only, no Collision or Comprehensive, any Bodily Injury limit | MINIMUM_LIABILITY |
| Collision and Comprehensive, Bodily Injury below 50,000 / 100,000 | BASIC_FULL_COVER |
| Collision and Comprehensive, Bodily Injury 50,000 / 100,000 or higher | REGULAR_FULL_COVER |
Example: Minimum, Better, Best and Customize tiers
| Partner tier | Send package |
|---|---|
| Minimum (25 / 50, 1,000 deductibles) | BASIC_FULL_COVER |
| Better, Best | REGULAR_FULL_COVER |
| Customize | The rows of the general table above, from the shopper's choices. |
The quote is the package, not your tier. Limits and deductibles come from the Just package and can differ from your tier's. Show the shopper package.name and package.coverages next to the price. A liability-only tier with high limits is still quoted at Just's Minimum Liability limits.
How RC1 quotes work#
At Just an RC1 quote is called a quick quote; you'll see that term in Just's emails, support replies and on just.insure. It means the same thing. RC1 quotes are priced from what you send. Missing or malformed input is a 400 that lists every problem, never a silent guess.
Start date, term and mileage#
| Rule | Detail | If not met |
|---|---|---|
| Start date | policyStartDate, today to 60 days ahead in the policyholder's time zone. Leave it out to start today. Show each quote's own policyStartDate: it's the date Just priced. | 400 POLICY_START_DATE_IN_PAST, POLICY_START_DATE_TOO_FAR_AHEAD |
| Full cover starts today | BASIC_FULL_COVER and REGULAR_FULL_COVER start today; MINIMUM_LIABILITY can start any day in the window. | Decline FUTURE_START_FULL_COVER_NOT_SUPPORTED |
| Term | Always 90 days, in term.days. There is no term field in the request. | — |
| Expiry | A quote and its clickToBuyUrl work until expiresAt, 30 days after pricing. | Request a new quote |
| Mileage | estimatedMonthlyMileage, whole miles a month, at least 1. Used for Pay-Per-Mile. | 400 OUT_OF_RANGE, INVALID_TYPE |
Eligibility is a quote#
There is no separate eligibility call. A quote means Just can offer the product; a decline means it can't, and says why. Just answers in this order:
Records and email#
Every call that reaches pricing (step 4) creates records at Just, even if you never show the price: a customer for an email Just hasn't seen before, or the existing customer for a known email, plus an application and a quote per product. Calls declined at step 3 create nothing.
Just emails the shopper only when you send notifyShopper: true. Then Just sends its usual quote email under its usual rules: an address at example.com is never emailed, and a shopper isn't emailed twice for the same quote. Leave it out, or send false, when your own page shows the prices and the consent to contact the shopper sits with you.
Create quotes#
Prices the shopper for each requested product, in order. Returns quotes, one quote object per product Just can offer, and declines, one decline per product it can't. A decline for one product never removes the other product's quote. Always read product rather than assuming two entries.
Returns
| Status | Meaning |
|---|---|
| 200 | Just evaluated the shopper. Body is { quotes[], declines[] }; both lists may be non-empty, and either may be empty. The call's id is in the Request-Id header. |
| 400 | The request has problems, all listed in errors. See field problem codes. |
| 401 | API key missing or not a Just key. From the gateway. |
| 403 | API key not enabled for this API. |
| 413 415 | Body over 64 KiB, or not application/json. |
| 500 502 504 | Just couldn't complete the quote. Safe to retry with backoff. |
{
"quotes": [
{
"id": "qq_01jaxk3m9v3t7q8r2w4y6z0abc",
"object": "quote",
"product": "PAY_PER_MILE",
"expiresAt": "2026-11-14T06:59:59Z",
"policyStartDate": "2026-10-15",
"term": { "days": 90 },
"package": {
"type": "BASIC_FULL_COVER",
"name": "Basic Full Cover",
"coverages": [
{
"type": "BODILY_INJURY",
"perPerson": { "amount": 2500000, "currency": "usd" },
"perAccident": { "amount": 5000000, "currency": "usd" }
},
{ "type": "PROPERTY_DAMAGE", "perAccident": { "amount": 1500000, "currency": "usd" } },
{ "type": "COLLISION", "deductible": { "amount": 100000, "currency": "usd" } },
{ "type": "COMPREHENSIVE", "deductible": { "amount": 100000, "currency": "usd" } },
{ "type": "GLASS" }
]
},
"price": {
"type": "PAY_PER_MILE",
"perDay": { "amount": 187, "currency": "usd" },
"perMile": { "amount": 5, "currency": "usd" },
"estimatedMonthlyMileage": 800,
"estimatedMonthlyCost": { "amount": 9610, "currency": "usd" },
"estimatedTermCost": { "amount": 28830, "currency": "usd" }
},
"paymentPlans": [
{
"default": true,
"interval": "day",
"intervalCount": 14,
"dueToday": {
"downPayment": { "amount": 4508, "currency": "usd" },
"fees": [{ "type": "AUTO_THEFT_FEE", "name": "Automobile Theft Authority Fee", "amount": { "amount": 50, "currency": "usd" } }],
"securityDeposit": { "amount": 5000, "currency": "usd" },
"total": { "amount": 9558, "currency": "usd" }
},
"installment": { "amount": 4508, "currency": "usd" }
}
],
"clickToBuyUrl": "https://staging.just.insure/authenticate?code=pq7f3c9a2e41b8d605&redirectUri=https%3A%2F%2Fstaging.just.insure%2Fquote%2Fapplication",
"warnings": []
},
{
"id": "qq_01jaxk3m9w5b2c8d4e6f7g9h0j",
"object": "quote",
"product": "UNLIMITED",
"expiresAt": "2026-11-14T06:59:59Z",
"policyStartDate": "2026-10-15",
"term": { "days": 90 },
"package": {
"type": "BASIC_FULL_COVER",
"name": "Basic Full Cover",
"coverages": [
{
"type": "BODILY_INJURY",
"perPerson": { "amount": 2500000, "currency": "usd" },
"perAccident": { "amount": 5000000, "currency": "usd" }
},
{ "type": "PROPERTY_DAMAGE", "perAccident": { "amount": 1500000, "currency": "usd" } },
{ "type": "COLLISION", "deductible": { "amount": 100000, "currency": "usd" } },
{ "type": "COMPREHENSIVE", "deductible": { "amount": 100000, "currency": "usd" } },
{ "type": "GLASS" }
]
},
"price": {
"type": "UNLIMITED",
"perDay": { "amount": 312, "currency": "usd" },
"termPremium": { "amount": 28080, "currency": "usd" }
},
"paymentPlans": [
{
"default": true,
"interval": "day",
"intervalCount": 14,
"dueToday": {
"downPayment": { "amount": 4368, "currency": "usd" },
"fees": [{ "type": "AUTO_THEFT_FEE", "name": "Automobile Theft Authority Fee", "amount": { "amount": 50, "currency": "usd" } }],
"securityDeposit": { "amount": 2808, "currency": "usd" },
"total": { "amount": 7226, "currency": "usd" }
},
"installment": { "amount": 4368, "currency": "usd" }
},
{
"default": false,
"interval": "day",
"intervalCount": 30,
"dueToday": {
"downPayment": { "amount": 9360, "currency": "usd" },
"fees": [{ "type": "AUTO_THEFT_FEE", "name": "Automobile Theft Authority Fee", "amount": { "amount": 50, "currency": "usd" } }],
"securityDeposit": { "amount": 2808, "currency": "usd" },
"total": { "amount": 12218, "currency": "usd" }
},
"installment": { "amount": 9360, "currency": "usd" }
}
],
"clickToBuyUrl": "https://staging.just.insure/authenticate?code=pq0b6e8d1f73a2c94e&redirectUri=https%3A%2F%2Fstaging.just.insure%2Fquote%2Fapplication",
"warnings": []
}
],
"declines": []
}
{
"quotes": [],
"declines": [
{
"product": "PAY_PER_MILE",
"code": "MULTIPLE_VEHICLES_NOT_SUPPORTED",
"message": "Just quotes one vehicle per request.",
"path": "vehicles"
},
{
"product": "UNLIMITED",
"code": "MULTIPLE_VEHICLES_NOT_SUPPORTED",
"message": "Just quotes one vehicle per request.",
"path": "vehicles"
}
]
}
{
"type": "https://docs.just.insure/quotes/errors#invalid-request",
"title": "Invalid request",
"status": 400,
"detail": "The request has problems listed in `errors`; fix them all and resend.",
"requestId": "req_01M504WZ3F1HEAD8X4A1JH69RE",
"errors": [
{
"path": "policyholder.phone",
"code": "INVALID_FORMAT",
"message": "Must be an E.164 phone number, e.g. +16025550143."
},
{
"path": "policyholder.dateOfBirth",
"code": "INVALID_DATE",
"message": "Must be an ISO 8601 date, YYYY-MM-DD."
},
{
"path": "vehicles[0]",
"code": "VEHICLE_IDENTIFIER_AMBIGUOUS",
"message": "Must use only one of: vin, partialVin."
},
{
"path": "vehicles[0].estimatedMonthlyMileage",
"code": "INVALID_TYPE",
"message": "Must be a whole number."
}
]
}
{
"type": "https://docs.just.insure/quotes/errors#dependency-failure",
"title": "Bad Gateway",
"status": 502,
"detail": "A service Just depends on failed. It is safe to retry.",
"requestId": "req_01M504X6TYH4QX4FR84G98PBSK"
}
{
"type": "https://docs.just.insure/quotes/errors#dependency-timeout",
"title": "Gateway Timeout",
"status": 504,
"detail": "Pricing took too long. It is safe to retry.",
"requestId": "req_01M504XEJDJMRNV7E9Z0C1HT0H"
}
Request body#
Field names are camelCase and case-sensitive; enum values are UPPER_SNAKE_CASE. Dates are ISO 8601 calendar dates, YYYY-MM-DD only (no time, no other ISO 8601 forms such as 19910412); timestamps in responses are ISO 8601 in UTC. Money is { "amount": <integer cents>, "currency": "usd" }. Types are strict: "800" where a number is expected is a 400, not converted. Unknown fields are ignored.
Required is a 400 MISSING_FIELD if missing. Optional can be left out. Nullable also accepts null; any other field sent as null is INVALID_TYPE.
The Just package to price. See packages and the mapping guide.
The person buying the policy, who is also its main driver: name, date of birth, contact details, address, credit band and driving history. Fields.
Other drivers, not the policyholder. Fields.
One vehicle per request for now. Quotes for several vehicles are planned for a future version; until then, more than one vehicle is a MULTIPLE_VEHICLES_NOT_SUPPORTED decline. Fields.
Which products to price, in this order. At least one, no repeats. Defaults to every live product: ["PAY_PER_MILE", "UNLIMITED"]. quotes and declines cover exactly these products.
From today to 60 days ahead, in the policyholder's time zone. Defaults to today. Full cover must start today. See start date rules.
Defaults to false: Just doesn't email the shopper. true sends Just's quote email. See records and email.
policyholder#
The policyholder's name.
A real calendar date, for example "1991-04-12".
Identifies the customer at Just. A new email creates a guest customer; a known email reuses that customer. Decides how clickToBuyUrl signs in.
Defaults to false. Send true only when you have verified that the shopper controls email, for example with a code you sent there. Just honours it only for partners it has agreed to trust; then a shopper who has quoted with Just before, but never held a policy, also gets a one-click link. Ask your Just contact whether your account is trusted.
For example "+16025550143".
Child attributes
Two uppercase letters. Picks the state's products and packages. A state Just doesn't sell in is an UNSUPPORTED_STATE decline.
12345 or 12345-6789; only the first five digits are used. A ZIP outside Just's area is an UNSUPPORTED_STATE decline at this path. A ZIP in a different state from state is a 400 INVALID_VALUE.
Prefill the shopper's address on just.insure. Send line1 and city when you have them.
The shopper's self-reported credit score. Send it when you have the exact score.
The shopper's self-reported credit band, when you don't have the exact score.
Send exactly one of creditScore or creditScoreBand. Neither is a 400 CREDIT_SCORE_REQUIRED, both is CREDIT_SCORE_AMBIGUOUS, at policyholder.
The shopper's cover before this policy.
Child attributes
Left out, the shopper is rated as INSURED. NEVER_INSURED is rated like a lapse in cover.
The previous insurer's name.
Used only when status is LAPSED. Values in reference values.
Saved on the shopper's application. Send them when you have them. Values in reference values.
The policyholder's driver licence; prefills the application.
Child attributes
Issuing state, two uppercase letters.
The policyholder's accidents, claims and violations. When sent, all three lists are required; send [] for none. Up to 50 events each.
Child attributes
occurredOn is a date, isAtFault and isAnyoneInjured booleans, amountOfLoss Money. All required.
Non-accident claims, such as theft. Both required.
occurredOn, a date, is required, plus exactly one of acdCode or severity. Both, or neither, is a 400 VIOLATION_IDENTIFIER_AMBIGUOUS or VIOLATION_IDENTIFIER_REQUIRED at policyholder.history.violations[j].
acdCode, string: the violation's AAMVA ACD code, for example "S11", in any letter case. Prefer it when you know the exact violation: Just prices that violation. It must be a code Just rates in the policyholder's state, listed in ACD violation codes; any other is INVALID_ENUM_VALUE at policyholder.history.violations[j].acdCode.
severity, enum: the fallback when you don't know the code. Just rates it as a generic major or minor violation. Use this guide, which follows how Just classes the ACD codes:
| Send | For | ACD codes |
|---|---|---|
MAJOR | Driving under the influence of alcohol or drugs, including refusing a test and underage drinking and driving; alcohol in the vehicle; hit and run or leaving an accident scene; racing; fleeing or evading police; using a vehicle in a felony; vehicular assault, homicide or manslaughter; a violation causing a fatal accident; a licence disqualification for serious violations. | A04, A08, A10, A11, A12, A20–A23, A26, A31, A35, A60, A61, B01–B08, B13, S95, U01, U03, U05–U08, U31, W30 |
MINOR | Everything else: speeding, signals and signs, lanes and turns, following too closely, equipment and documents, and similar moving violations. | Every other code in ACD violation codes |
When in doubt, or for reckless or careless driving, send the acdCode rather than guessing a severity.
additionalDrivers#
Other people who drive the vehicle, up to 9; leave it out or send [] when the policyholder is the only driver. The policyholder is never listed here. Any driver outside the insurable age range declines every product with DRIVER_NOT_ELIGIBLE, at policyholder or additionalDrivers[i].
Relationship to the policyholder.
A real calendar date, for example "1992-09-30".
Same fields as policyholder.licence.
Same fields and rules as policyholder.history; violation problems are at additionalDrivers[i].history.violations[j].
vehicles#
Identify each vehicle by exactly one of vin or partialVin, and give its monthly mileage. A vehicle with neither is VEHICLE_IDENTIFIER_REQUIRED; with both, it's VEHICLE_IDENTIFIER_AMBIGUOUS. Year, make and model aren't accepted in v1; a vehicle sent only that way is VEHICLE_IDENTIFIER_REQUIRED.
| Identifier | Fields | Example |
|---|---|---|
| Full VIN | vin | { "vin": "1GC0K9CG0BF213909", "estimatedMonthlyMileage": 600 } |
| Partial VIN | partialVin | { "partialVin": "19XFA1F5*A", "estimatedMonthlyMileage": 800 } |
17 letters or digits. A VIN that doesn't decode to a vehicle Just knows is a VEHICLE_NOT_FOUND decline.
The first 8 VIN characters, * in place of the check digit, then the 10th (model year) character: 19XFA1F5*A.
Miles a month, echoed in the Pay-Per-Mile price. See mileage.
A vehicle Just doesn't insure is a VEHICLE_NOT_INSURABLE decline.
The quote object#
A 200 returns quotes and declines; the call's id is in the Request-Id header, not the body. Every amount is Money in integer cents, never fractional. Response objects can gain fields and enums can gain values at any time; ignore what you don't know (see compatibility).
Just's id for this quote: qq_ followed by 26 lowercase letters and digits, for example qq_01jaxk3m9v3t7q8r2w4y6z0abc. Each quote has its own; a new call creates new quotes with new ids. Store it with the price you show, and send it to Just, with the call's Request-Id, in any question about the quote. Compare it as a whole string; don't parse it.
Always "quote". Says what kind of object this is, so a stored or logged object explains itself. The qq_ prefix of id says the same.
Which product this quote is for.
When the price expires, 30 days after the quote. clickToBuyUrl stops working then. May carry milliseconds, for example 2026-11-14T06:59:59.999Z.
The start date Just priced, in the policyholder's time zone.
days: the length of the term. 90.
type is the package priced, the one you asked for. name is its display name, for example "Basic Full Cover". coverages lists what it covers; see below.
The rate, shaped by product. See price.
How the term is billed. See payment plans.
Opens this quote on just.insure. A credential; see sign-in.
Notes about the quote. See declines and warnings.
price#
price.type matches product and decides the shape.
PAY_PER_MILE | Meaning |
|---|---|
perDay | Daily rate. |
perMile | Rate per mile driven. |
estimatedMonthlyMileage | The mileage the estimates use, as you sent it. An integer, not Money. |
estimatedMonthlyCost | Estimated cost of 30 days at that mileage. |
estimatedTermCost | Estimated cost of the term: estimatedMonthlyCost × 3 for 90 days. |
UNLIMITED | Meaning |
|---|---|
perDay | Daily rate. |
termPremium | Cost of the term: perDay × term.days. |
paymentPlans#
Every plan is Scheduled Pay: the customer pays the first bill to start, then Just bills the same amount every cycle. Pay-Per-Mile bills every 14 days, at the estimate from estimatedMonthlyMileage; Just adjusts later bills up or down using the odometer readings the customer provides. Unlimited bills every 14 days (the default) or every 30 days. Show the plan with default: true first.
The plan to show first. One per quote.
The billing cycle: every intervalCount intervals. Just expresses cycles in days: every 14 days is day × 14, every 30 days is day × 30 (not a calendar month).
What the customer pays to start. Show total as the price to start.
Child attributes
The first bill: the first cycle's charge, the same amount as installment.
Fees charged on the first bill, one entry per fee; [] when there are none. Each has type (a stable code), name (for display) and amount (Money). Today the only fee is Arizona's AUTO_THEFT_FEE, "Automobile Theft Authority Fee", 50 cents per vehicle; other states have no fees.
Refundable, and not premium.
downPayment + the sum of fees + securityDeposit.
Each regular bill: one full cycle's charge, the same every cycle. For Pay-Per-Mile it's an estimate at estimatedMonthlyMileage; Just adjusts later bills using the customer's odometer readings, so installment is an estimate.
Every bill is a number of days × the daily rate:
perDay + perMile × ⌈estimatedMonthlyMileage ÷ 30⌉, the miles a day rounded up. Unlimited: perDay.downPayment and installment.In the example on the right, Pay-Per-Mile's daily rate is 187 + 5 × ⌈800 ÷ 30⌉ = 187 + 5 × 27 = 322 cents. A 14-day bill is 4,508. In cents:
| Pay-Per-Mile, 14 days | Unlimited, 14 days | Unlimited, 30 days | |
|---|---|---|---|
| Daily rate | 322 | 312 | 312 |
First bill (downPayment) | 4,508 | 4,368 | 9,360 |
installment | 4,508 | 4,368 | 9,360 |
fees (Arizona), first bill only | 50 | 50 | 50 |
securityDeposit, refundable | 5,000 | 2,808 | 2,808 |
dueToday.total | 9,558 | 7,226 | 12,218 |
Pay-Per-Mile bills start from the estimate and are adjusted using the customer's odometer readings. Fees and the security deposit are on top of the bills. The example is in Arizona, so each plan includes the 50-cent Automobile Theft Authority Fee.
package.coverages#
One entry per coverage in the package. A limit or deductible that doesn't apply is left out; GLASS, for example, has none.
Values in reference values. A state that sells Uninsured and Underinsured Motorist BI as one cover returns UNINSURED_UNDERINSURED_MOTORIST_BI; otherwise they are separate entries.
Limits. Bodily Injury has both; Property Damage has perAccident.
For Collision and Comprehensive.
clickToBuyUrl sign-in#
Link the shopper to clickToBuyUrl from the price you show. It opens this quote on just.insure with the product and package selected. Whether it also signs the shopper in depends on who the email belongs to:
Shopper, by policyholder.email | The link |
|---|---|
| New to Just | Signs in with one click |
Has quoted with Just before, never held a policy, and you sent emailVerified: true as a partner Just trusts | Signs in with one click |
| Has quoted with Just before, never held a policy, otherwise | Opens the quote after the shopper signs in by email |
| Holds or has held a Just policy | Opens the quote after the shopper signs in by email, always |
expiresAt, 30 days at most.If Just can't create a one-click link, you still get a working link that asks the shopper to sign in. The quote is never dropped over the link.
Declines and warnings#
A decline says Just can't offer a product to this shopper. It's an answer, not an error: the call is still 200, and retrying the same request gives the same decline. Show no Just price for that product.
The product declined. Every requested product appears in either quotes or declines.
Why. Branch on this. See decline codes.
For people, in English. It can change; don't parse it.
The request field the decline is about, for example policyholder.address.zipCode or additionalDrivers[0].
warnings#
Each quote carries warnings: { code, message? }. A warning never stops you showing the quote. The list is empty today. VEHICLE_ASSUMED is reserved for a quote priced on a vehicle Just matched approximately; accept codes you don't know.
{
"quotes": [
{
"id": "qq_01jaxk3mb0n4p6r8s2t5v7x9zc",
"object": "quote",
"product": "PAY_PER_MILE",
"expiresAt": "2026-11-14T06:59:59Z",
"policyStartDate": "2026-10-15",
"term": { "days": 90 },
"package": {
"type": "MINIMUM_LIABILITY",
"name": "Minimum Liability",
"coverages": [
{
"type": "BODILY_INJURY",
"perPerson": { "amount": 2500000, "currency": "usd" },
"perAccident": { "amount": 5000000, "currency": "usd" }
},
{ "type": "PROPERTY_DAMAGE", "perAccident": { "amount": 1500000, "currency": "usd" } }
]
},
"price": {
"type": "PAY_PER_MILE",
"perDay": { "amount": 98, "currency": "usd" },
"perMile": { "amount": 3, "currency": "usd" },
"estimatedMonthlyMileage": 500,
"estimatedMonthlyCost": { "amount": 4440, "currency": "usd" },
"estimatedTermCost": { "amount": 13320, "currency": "usd" }
},
"paymentPlans": [
{
"default": true,
"interval": "day",
"intervalCount": 14,
"dueToday": {
"downPayment": { "amount": 2086, "currency": "usd" },
"fees": [{ "type": "AUTO_THEFT_FEE", "name": "Automobile Theft Authority Fee", "amount": { "amount": 50, "currency": "usd" } }],
"securityDeposit": { "amount": 5000, "currency": "usd" },
"total": { "amount": 7136, "currency": "usd" }
},
"installment": { "amount": 2086, "currency": "usd" }
}
],
"clickToBuyUrl": "https://staging.just.insure/quote/application?quote=qq_01jaxk3mb0n4p6r8s2t5v7x9zc&utm_source=partner",
"warnings": []
}
],
"declines": [
{
"product": "UNLIMITED",
"code": "UNDERWRITING_DECLINED",
"message": "Unlimited cannot be offered to this shopper."
}
]
}Decline codes#
The code of a decline. Every product means each requested product gets the same decline.
code | Category | Scope | path | Meaning | What to do |
|---|---|---|---|---|---|
UNSUPPORTED_STATE | Eligibility | Every product | policyholder.address.state | Just doesn't sell in this state. | Fine to call: hide Just for this shopper, or skip the call for other states. |
UNSUPPORTED_STATE | Eligibility | Every product | policyholder.address.zipCode | The ZIP is outside the area Just covers, or not one Just recognises. | Check the ZIP. |
UNSUPPORTED_STATE | Eligibility | That product | policyholder.address.state | This product isn't sold in the state. | Show the other product. |
MULTIPLE_VEHICLES_NOT_SUPPORTED | Eligibility | Every product | vehicles | More than one vehicle. | Fine to call: hide Just for this shopper, or skip the call for multi-vehicle households. |
FUTURE_START_FULL_COVER_NOT_SUPPORTED | Eligibility | Every product | policyStartDate | A full-cover package with a start after today. | Start today, or quote MINIMUM_LIABILITY. |
VEHICLE_NOT_FOUND | Eligibility | Every product | vehicles[0] | The VIN or partial VIN doesn't decode to a vehicle Just knows. | Check the VIN or partial VIN for typos and resend; if it's correct, Just can't quote this vehicle. |
VEHICLE_NOT_INSURABLE | Eligibility | Every product | vehicles[0] | Just doesn't insure this vehicle. | Not quotable. |
DRIVER_NOT_ELIGIBLE | Eligibility | Every product | policyholder or additionalDrivers[i] | A driver is outside the insurable age range. | Not quotable with that driver. |
PACKAGE_NOT_AVAILABLE | Eligibility | That product | package | This product doesn't offer the package for this shopper. | Try another package if your tiers allow. |
UNDERWRITING_DECLINED | Underwriting | That product | none | Just declined the risk, for example too many claims or violations. | Not quotable. |
New codes may be added. Treat a code you don't know as a decline for that product.
Compatibility policy#
The version is in the URL. Within /v1, Just only makes changes that don't break a client that follows the two rules below.
/v1 for at least 6 months.Your two rules. Ignore response fields you don't know, and handle enum values you don't know. If you validate responses against Just's schema, it allows both: objects are open and response enums list their known values as examples.
Reference values#
Every enum in the contract. Request enums are closed: anything else is INVALID_ENUM_VALUE. Response enums are open: expect values not listed here.
Shared
Product: request products[], response product
Package: request package, response package.type
Money.currency
Request
additionalDrivers[].relationship
policyholder.gender, additionalDrivers[].gender
policyholder.history.violations[].severity, additionalDrivers[].history.violations[].severity
policyholder.history.violations[].acdCode, additionalDrivers[].history.violations[].acdCode
An AAMVA ACD code from the policyholder's state list, in any letter case. See ACD violation codes.
policyholder.creditScoreBand
policyholder.homeOwnership
policyholder.maritalStatus
policyholder.education
policyholder.employmentStatus
policyholder.priorInsurance.status
policyholder.priorInsurance.reasonForLapse
Response
package.coverages[].type
price.type
paymentPlans[].interval
declines[].code
quotes[].warnings[].code
Error type names and field problem codes are listed on the errors page.
ACD violation codes#
The AAMVA ACD codes Just rates, for policyholder.history.violations[].acdCode and additionalDrivers[].history.violations[].acdCode. Codes are case-insensitive. Just publishes the list per state. Today Arizona and Indiana accept the same 142 codes below, and Nevada accepts codes from the same list. A state's list can change, and lists can differ between states in future. A code that isn't on the policyholder's state list is INVALID_ENUM_VALUE; when you don't know the code, send severity instead.
142 codes
| Code | Description |
|---|---|
A04 | Driving under the influence of alcohol with BAC at or over .04 |
A08 | Driving under the influence of alcohol with BAC at or over .08 |
A10 | Driving under the influence of alcohol with BAC at or over .10 |
A11 | Driving under the influence of alcohol with BAC at or over ___(detail field required) |
A12 | Refused to submit to test for alcohol - Loss resulted |
A20 | Driving under the influence of alcohol or drugs |
A21 | Driving under the influence of alcohol |
A22 | Driving under the influence of drugs |
A23 | Driving under the influence of alcohol and drugs |
A25 | Driving while impaired |
A26 | Drinking alcohol while operating a vehicle |
A31 | Illegal possession of alcohol |
A35 | Possession of open alcohol container |
A60 | — |
A61 | Underage Administrative Per Se - drinking and driving at .02 or higher BAC |
B01 | Hit and run - failure to stop and render aid after accident |
B02 | Hit and run - failure to stop and render aid after accident - FATAL accident |
B03 | Hit and run - failure to stop and render aid after accident - Personal injury accident |
B04 | Hit and run - failure to stop and render aid after accident - Property damage accident |
B05 | Leaving accident scene before police arrive |
B06 | Leaving accident scene before police arrive - FATAL accident |
B07 | Leaving accident scene before police arrive - Personal injury accident |
B08 | Leaving accident scene before police arrive - Property damage accident |
B13 | — |
B20 | Driving while license withdrawn |
B22 | Driving while license cancelled |
B23 | Driving while license denied |
B24 | Driving while license disqualified |
B25 | Driving while license revoked |
B26 | Driving while license suspended |
B61 | Failed to file accident report |
B91 | Failed to file future proof of financial responsibility |
D06 | Misrepresentation of identity or other facts on application for driver license |
D16 | Show or use improperly - Loss of Driver License |
D29 | Violate restrictions of driver license (includes DL, CDL, and Instruction Permit) |
D70 | Driver's view obstructed |
E31 | Failure to obtain or display farm vehicle plates when required |
E54 | Failure to use headlight dimmer as required |
E55 | Failure to use lights as required |
F03 | — |
F06 | — |
F22 | — |
F34 | Stopping, standing, or parking: obstructing or impeding traffic |
F35 | — |
M04 | Failure to obey flagger |
M08 | Failure to obey police or peace officer |
M12 | Failure to obey safety zone |
M16 | Failure to obey traffic signal or light |
M19 | Failure to obey yield sign |
M30 | Following improperly |
M32 | Following emergency vehicle unlawfully |
M33 | Following fire equipment unlawfully |
M34 | Following too closely |
M40 | Improper lane or location |
M41 | Failure to keep in proper lane |
M42 | Improper or erratic (unsafe) lane changes |
M44 | Improper lane or location - crossover |
M45 | Improper lane or location - crosswalk |
M46 | Improper lane or location - entrance/exit ramp or way |
M48 | Improper lane or location - in occupied lane |
M49 | Improper lane or location - in HOV or restricted lane |
M50 | Improper lane or location - limited access highway |
M51 | Improper lane or location - median |
M56 | Improper lane or location - on fire hose |
M57 | Improper lane or location - oncoming traffic lane |
M58 | Improper lane or location - road shoulder, ditch or sidewalk |
M60 | Improper lane or location - slower vehicle lane |
M61 | Improper lane or location - straddling center line(s) |
M62 | Improper lane or location - traveling in turn (or center) lane |
M70 | Improper passing |
M71 | Passing in violation of posted sign or pavement marking |
M73 | Passing on wrong side |
M74 | Passing on hill or curve |
M75 | Passing school bus displaying warning not to pass |
M76 | Passing where prohibited |
M77 | Passing with insufficient distance or visibility |
M80 | Inattentive, careless, or negligent driving |
M81 | Careless driving |
M82 | Inattentive driving |
M83 | Negligent driving |
M84 | Reckless driving |
N01 | Failure to yield right of way |
N03 | Failure to yield right of way to cyclist |
N04 | Failure to yield right of way to emergency vehicle (i.e. ambulance, fire equipment, police) |
N05 | Failure to yield right of way to funeral pocession, procession or parade |
N06 | Failure to yield right of way to other vehicle |
N08 | Failure to yield right of way to pedestrian (includes handicapped or blind) |
N20 | Failure to yield right of way at crosswalk |
N22 | Failure to yield right of way at stop sign |
N23 | Failure to yield right of way at traffic sign |
N24 | Failure to yield right of way at traffic signal |
N25 | Failure to yield right of way at unsigned intersection |
N26 | Failure to yield right of way at yield sign |
N31 | Failure to yield right of way W when turning |
N40 | Failure to use or improper signal |
N43 | Failure to signal lane change or turn |
N44 | Giving wrong signal |
N50 | Improper turn |
N51 | Improper method of turning |
N52 | Improper position for turning |
N53 | Making improper left turn |
N54 | Making improper right turn |
N55 | Making improper turn around (not U turn) |
N56 | Making improper U turn |
N60 | Driving wrong way |
N61 | Driving wrong way at rotary intersection |
N62 | Driving wrong way on divided highway |
N63 | Driving wrong way on one way street or road |
N70 | Driving on wrong side |
N71 | Driving on wrong side of divided highway |
N72 | Driving on wrong side of undivided street or road |
N82 | Improper backing |
N83 | Improper start from parked position |
S01 | 01-05>Speed limit (detail optional) |
S06 | 06-10>Speed limit (detail optional) |
S11 | 11-15>Speed Limit (detail optional) |
S14 | Speeding - 11-14 MPH over limit |
S15 | Speeding 15 mph or more above speed limit (detail optional) |
S16 | 16-20>Speed limit (detail optional) |
S21 | 21-25>Speed limit (detail optional) |
S26 | 26-30>Speed limit (detail optional) |
S31 | 31-35 > Speed limit (detail optional) |
S36 | 36-40>Speed limit (detail optional) |
S41 | 41+ >Speed limit (detail optional) |
S51 | 01-10>Speed limit (detail optional) |
S61 | 11-20>Speed limit (detail optional) |
S71 | 21-30>Speed limit (detail optional) |
S81 | 31-40>Speed limit (detail optional) |
S91 | 41+>Speed limit (detail optional) |
S94 | Prima Facie speed violation or driving too fast for conditions |
S95 | Speed contest (racing) on road open to traffic |
S96 | Speed less than minimum |
S97 | Operating at erratic or suddenly changing speeds |
S99 | Speeding in a school zone |
U01 | Fleeing or evading police or roadblock |
U03 | Using a motor vehicle in connection with a felony (not traffic offense) |
U05 | Using a motor vehicle to aid and abet a felon |
U06 | Vehicular assault |
U07 | Vehicular homicide |
U08 | Vehicular manslaughter |
U31 | Violation resulting in fatal accident |
W30 | 60 day disqualification due to 2 serious violations in 3 years |
Changelog#
First release of the Quotes API: POST /v1/quotes returns RC1 quotes for Just Pay-Per-Mile and Just Unlimited in Arizona, Nevada and Indiana, with per-product declines, amounts in integer cents, RFC 9457 errors and a single-use clickToBuyUrl. A vehicle is identified by vin or partialVin.
Request shape: policyholder holds the policyholder's own driver details (name, date of birth, gender, licence, history); additionalDrivers lists any other drivers.
Planned: identify a vehicle by year, make and model; quote several vehicles in one request.
Request-Id response header of the call, and the quote's id for a question about a quote, so Just can find it.