A paid HTTP endpoint that answers one question with a cited verdict: can this specific licensed, insured vehicle take this kind of trip? Operated by upgo.ai inc. Fleet and credential data belong to Volt and Velvet Mobility LLC, a TCP-licensed California charter-party carrier (TCP 51207-B).
Payment is the only admission: the first request returns
HTTP 402 with machine-readable payment requirements; a request
carrying a valid signed payment returns the verdict. There is no signup and
no prior contact with us required. Anything on this page can be verified
before paying — the 402 quote below is retrievable with one curl.
0.10 USDC per answered query — flat, on Base mainnet. No account, no API key, no subscription, no minimum.
vehicle-eligibility/v1 response — checks[] with
stable machine codes, the ledger citations each check was decided on, and an
on-chain settlement receipt (transaction hash) in the response headers.400) is never charged.
Parameters are validated before settlement; a rejected request costs
nothing.402 quote is authoritative. If this
page and a live 402 ever disagree, the 402 is
correct.| Param | Type | Default | Meaning |
|---|---|---|---|
airport | 3-letter code | — | Airport the trip touches (pickup or dropoff). Omitted = non-airport ground trip, so no airport-permit check runs. |
passengers | int 1–99 | 1 | Party size, checked against the vehicle's seat count. |
trip_date | YYYY-MM-DD | today (UTC) | Permits and insurance are term-bounded; the verdict is for this date. |
vin | string | the single registered vehicle | Which asset. Explicit vin becomes required once the fleet is larger than one. |
HTTP 402 with two forms of the same quote: a v1 JSON body whose
accepts[0] is shown below, and a PAYMENT-REQUIRED
response header carrying the base64 x402 v2 quote.
{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "100000",
"resource": "https://viql.upgo.ai/viql/vvm/paid/vehicle/eligibility",
"description": "Cited compliance eligibility verdict (checks[] + ledger provenance)",
"mimeType": "application/json",
"payTo": "0x8C2d7c8495245c25De74C900aF7057f1608A19F8",
"maxTimeoutSeconds": 60,
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"extra": { "name": "USD Coin", "version": "2" }
}
100000 is atomic USDC units (6 decimals) = 0.10 USDC.
asset is the USDC contract on Base mainnet.transferWithAuthorization for that amount to
payTo, from a wallet holding USDC on Base. No ETH is needed —
settlement is broadcast by the facilitator, not by you. The x402 client
libraries below do this signing for you.X-PAYMENT: <base64 payload> (the 402
body is the v1 shape: maxAmountRequired, plain
base network id);
v2 clients send PAYMENT-SIGNATURE: <base64 payload> (the
402's PAYMENT-REQUIRED header carries the base64 v2
quote: amount, CAIP-2 eip155:8453 network id).
Whichever header you send selects the flow; both settle the same way at the
same price.200. The response carries a base64 settlement
receipt including the transaction hash — in X-PAYMENT-RESPONSE
on the v1 flow, PAYMENT-RESPONSE on the v2 flow.Billing rules, exactly as implemented:
400) is never charged — parameters are validated before settlement.402) — there are no free verdicts on this route.402 body is the authoritative quote at call time. If this page and a live 402 ever disagree, the 402 is correct.Inspect the quote first — costs nothing, requires nothing:
curl -i "https://viql.upgo.ai/viql/vvm/paid/vehicle/eligibility?airport=OAK&passengers=4"
# → HTTP/2 402 + the accepts[] payment requirements shown above
Paid call (Node 18+; wallet key holds ≥ 0.10 USDC on Base mainnet, zero ETH required):
// npm install x402-fetch viem
import { privateKeyToAccount } from "viem/accounts";
import { wrapFetchWithPayment } from "x402-fetch";
const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY);
const payFetch = wrapFetchWithPayment(fetch, account);
const res = await payFetch(
"https://viql.upgo.ai/viql/vvm/paid/vehicle/eligibility"
+ "?airport=OAK&passengers=4"
);
console.log(res.status); // 200
console.log(res.headers.get("x-payment-response")); // base64 settlement receipt (tx hash)
console.log(await res.json()); // the cited verdict
Python equivalent: the x402 package on PyPI wraps
httpx/requests the same way.
Schema vehicle-eligibility/v1. eligible is never a
bare boolean — every verdict decomposes into checks[], each with a
stable machine code, a human-readable reason, and the
ledger basis it was decided on:
{
"primitive": "viql.vehicle.eligibility",
"schema": "vehicle-eligibility/v1",
"eligible": false,
"reasons": ["not_permitted_at_airport"],
"vehicle": { "name": "2026 Toyota Sequoia Platinum", "vin": "7SVAAABA8TX085006",
"seats": 7, "type": "vehicle", "operated_by": "Volt and Velvet Mobility LLC" },
"trip": { "airport": "SFO", "passengers": 4, "trip_date": "2026-07-21", "same_day": true },
"checks": [
{ "dimension": "airport_permit", "status": "fail", "code": "not_permitted_at_airport",
"reason": "no airport permit on the ledger for SFO",
"basis": [{ "source": "ENTITIES.md § vvm", "finding": "no airport_permit entry with airport=SFO" }] },
{ "dimension": "insurance", "status": "pass", "code": "ok", "...": "..." }
],
"provenance": { "ledger": "ENTITIES.md § vvm", "ledger_sha256": "…64 hex…",
"read_model": "build-time snapshot, drift-gated in CI" }
}
pass | fail | unknown | not_evaluated — the endpoint says which, it does not guess.not_permitted_at_airport, insufficient_capacity, asset_unavailable, insurance_not_in_force, permit_expired, …) are actionable: an agent can retry OAK instead of SFO, split the party, or pick another date.provenance.ledger_sha256 pins the exact compliance-ledger state that produced the verdict.not_permitted_at_airport by cited absence — meaning "VVM holds no permit there," not "no operator may go there."not_evaluated on availability. A telemetry outage yields unknown and never flips a ledger-based verdict.An OpenAPI document for this API is served at
/openapi.json —
parameters, response schemas, and x-payment-info pricing, in the
format x402 indexers (x402scan, Bazaar) and agent toolchains consume.
A free sibling route exists for named, allowlisted partners; this paid route is the only open admission path. A booking-intent endpoint exists but is allowlisted and stops at reviewable intent — it cannot reach "booked."