VIQL — vehicle-eligibility API

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).

GET https://viql.upgo.ai/viql/vvm/paid/vehicle/eligibility
0.10 USDC per answered query · x402 protocol (v1 + v2 dual-stack) · Base mainnet · no API key, no account, no allowlist

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.

Pricing

0.10 USDC per answered query — flat, on Base mainnet. No account, no API key, no subscription, no minimum.

Query parameters

ParamTypeDefaultMeaning
airport3-letter code—Airport the trip touches (pickup or dropoff). Omitted = non-airport ground trip, so no airport-permit check runs.
passengersint 1–991Party size, checked against the vehicle's seat count.
trip_dateYYYY-MM-DDtoday (UTC)Permits and insurance are term-bounded; the verdict is for this date.
vinstringthe single registered vehicleWhich asset. Explicit vin becomes required once the fleet is larger than one.

How payment works (x402)

  1. Call the endpoint with no payment header. The response is 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.
  2. Sign an EIP-3009 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.
  3. Retry the same request carrying the signed payment. This endpoint is dual-stack — it speaks x402 v1 and v2 and recognizes both client generations: v1 clients send 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.
  4. The server verifies the payment cryptographically (Coinbase CDP facilitator), computes the verdict, settles the transfer on-chain, and only then responds 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:

Copy-pasteable example

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.

What you get back

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" }
}

What this endpoint cannot do

Machine discovery

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.

Related surfaces

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."