# Last Price > Authenticated price computation, agent workspaces and recorded usage. ## Ways in (pick one) These are independent options, not steps. OAuth registration is an additional option beside self-registration, not a replacement. - Just trying it, no key: `POST https://api.last-price.ai/api/public/compute/demo` or MCP at `https://api.last-price.ai/api/mcp/rpc` (limited, see below). - A free API key right now, no human: `POST https://api.last-price.ai/api/agents/register` (sandbox workspace, claim link for a person). - An OAuth client for a client-credentials framework: `POST https://api.last-price.ai/api/oauth/register` (RFC 7591), then `client_credentials` at `POST https://api.last-price.ai/api/oauth/token`. Same sandbox as self-registration; `client_secret_expires_at` is the sandbox key expiry, and a claim lifts it. - No account, pay per call: `POST https://api.last-price.ai/api/compute/price` with no credential answers 402 with x402 payment requirements (see "Pay per call" below). - A workspace of your own, signed in as an agent: AgentID with an inbox you control at https://app.last-price.ai/sign-up, then create an API key in Settings. - A person-owned account: a person signs up at https://app.last-price.ai/sign-up and creates an API key or agent-bound key for you. ## Try it without an account - Missing pricing inputs? `POST https://api.last-price.ai/api/compute/conversation` with `{}` or call MCP `pricing_conversation`. Return its questions to your caller, then send the returned continuation plus answers. Preparation is free; action `compute` uses normal pricing access and billing. Never guess missing costs or bounds. - `POST https://api.last-price.ai/api/public/compute/demo` with `{"context":{"product_type":"saas","current_price":49,"currency":"USD"}}`: a real price computation on a demo tenant. No key, 30 calls per IP per hour. - `POST https://api.last-price.ai/api/public/price-router/verify` with `{"proposed_price":49,"context":{"product_type":"saas","current_price":49,"currency":"USD"}}`: whether a price you are about to charge is sound. - `GET https://api.last-price.ai/api/functions/catalog` and `GET https://api.last-price.ai/api/marketplace/listings`: browse the public function catalog and marketplace listings. No key, 60 calls per IP per minute each; a key sent here is ignored. Your own listings (`?scope=owned`) need a key. - MCP: `https://api.last-price.ai/api/mcp/rpc` (Streamable HTTP, or plain JSON-RPC 2.0 by POST; manifest at /.well-known/mcp.json). Without a key its pricing tools use the demo above. Each tool call has 30 seconds; past that it answers JSON-RPC error -32001 with `data.code` `upstream_timeout` and a `hint`: send the same call again once. Production pricing is `POST /api/compute/price` with the same body and an API key in `x-api-key`. ## Pay per call, no account (x402) `POST https://api.last-price.ai/api/compute/price` with no credential answers `402 Payment Required` with x402 payment requirements: scheme `exact`, network `base`, 0.01 USDC per call (asset 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913), paid to 0x30F4f41158dBd194B51820E5633fCBa8eBD86ea4. - Sign the payment with your wallet and repeat the same call with it, base64 encoded, in the `X-PAYMENT` header. The result comes back with an `X-PAYMENT-RESPONSE` header holding the settlement transaction. - x402 v2 clients work too: the requirements are also in the `PAYMENT-REQUIRED` header (network `eip155:8453`), the payment goes in `PAYMENT-SIGNATURE`, and the settlement comes back in `PAYMENT-RESPONSE`. - Each payment buys exactly one call and is refused if presented again. It is settled only after the price is computed, so a failed call is never charged. - If settlement is refused (`payment_settlement_failed` with `retryable: true`), nothing was charged and the same payment may be presented again, up to 3 settlement attempts in all. - If the answer is `payment_settlement_unknown` (503, `retryable: false`), the payment may have been charged: do not sign a new payment for that call. Contact support@last-price.ai with the `payment_id` it carries. - Paid calls run on a shared pay-per-call workspace with the built-in and publicly listed functions. An API key works on the same endpoint instead. - Last Price's own x402 pays for compute. It is not a way to sign up. AgentMail's x402 gateway pays for AgentMail API calls, such as creating an inbox, without an AgentMail API key. It does not sign you in to Last Price. AgentID sign-in needs an AgentMail API key with provider_connect permission, and an x402 call does not carry one. - A self-registered agent key can pay too, for instance once its daily compute limit is reached: send the same `POST /api/compute/price` or `POST /api/price-router` request with the key and a payment header. It runs now on the agent's own workspace at the same price and does not count against the limit. On any other plan a payment header next to a key is ignored. - Or prepay: `POST https://api.last-price.ai/api/billing/topup` with `{"amount":""}` (at least 10) and one x402 payment for exactly that amount credits your workspace balance, with a bonus on top-ups of 100 USDC or more. Compute then draws 0.008333 USDC a call from it instead of 0.01 per call (a batch on a workspace with balance billing on draws one call per item, all or nothing), and nothing is ever charged automatically (`GET /api/billing/balance` shows the balance). - Or buy a day pass with the same key: `POST https://api.last-price.ai/api/agents/allowance` with one x402 payment of 2.5 USDC adds 500 compute calls for 24 hours, used once the daily limit is reached. Without a payment it answers 402 with the requirements; `GET` the same path lists your passes and the calls left. It is refused (409 `sandbox_key_expiring`, nothing charged) when your key expires within 24 hours. A compute request sent with a payment header is paid per call even while a pass is live. Unused pass calls are forfeited when a person claims the workspace. ## Get an API key with no human - `POST https://api.last-price.ai/api/agents/register` with `{"name":"your-system/role-name"}` (optional `contact_email`, `intended_use`). No credential needed. Returns `201` with a sandbox workspace, an API key shown once in `api_key.key`, and a `claim.claim_url`. - Send the key as `x-api-key`. It can compute prices with built-in functions (`POST /api/compute/price`, `POST /api/price-router`, `POST /api/price-router/verify`), read functions and routing policies, and call `GET /api/me`. Scopes: `price:compute`, `pcn:function:read`, `pcn:routing:read`. Anything else answers 403 `sandbox_restricted`. - Limits: 25 compute calls per day, 5 registrations per address per day, and the key expires after 30 days. - Rotate the key yourself with `POST /api/api-keys/rotate` (the key in `x-api-key`): the new key keeps the same scopes and expiry, and the old one stops working at once. - The same key is an OAuth client: `client_id` is `api_key.key_prefix`, `client_secret` is the key, at `POST /api/oauth/token` with `grant_type=client_credentials`. - Or, if your OAuth client-credentials framework expects to register its own client, register one at `POST https://api.last-price.ai/api/oauth/register` (RFC 7591, `client_credentials` only, no authorization code flow) for the same sandbox; it returns `client_id` and `client_secret`, and `client_secret_expires_at` is the sandbox key expiry, which a claim lifts. Server metadata: `/.well-known/oauth-authorization-server`. Both routes stay available; use either. - Give `claim_url` to a person. When they sign in and claim it, the workspace joins their account and the sandbox limits lift. The link works once. ## Being attributed Send a descriptive `User-Agent` on every call, such as `your-system/role-name` or `YourAgent/1.0`. The workspace's live traffic view names each request by it. - With an API key, a request counts as the workspace's own. Several agents can share one workspace key and tell themselves apart by User-Agent. - An agent-bound key (`POST /api/agents`, then `POST /api/agents/{id}/keys`) is optional. It adds the agent's name, per-agent scopes and revocation. - Keyless calls (the demo and MCP without a key) never count as a workspace's own traffic, whatever User-Agent they send. ## Keys for a signed-in account - To compute, a key needs the `price:compute` scope. Pick it in the Settings API key dialog at https://app.last-price.ai/settings/api-keys. - A legacy `write` or `admin` key still authenticates `GET /api/me`, but `POST /api/compute/price` answers 403 `insufficient_scope`. Create a new key with `price:compute`. - Creating an agent and its key needs a person's credential: a dashboard session or a JWT not bound to an agent. An API key cannot do it and gets 401. A JWT bound to an agent gets 403. - Holding a Supabase session but no API key? Make three calls. 1) `POST /api/auth/native-token` with the Supabase access token as `Authorization: Bearer`; it returns a one-hour Last Price JWT in `access_token`. 2) `POST /api/agents` with that JWT as `Authorization: Bearer` and `{"name":"your-system/role-name","scopes":["price:compute"]}`; the agent id is in `data.agent.id`. 3) `POST /api/agents/{id}/keys` with the same JWT and `{"name":"compute","scopes":["price:compute"]}`. The key is shown once in `data.api_key.key`; send it as `x-api-key`. ## Start here - [Agent signup guide](https://last-price.ai/agent-sign-in): Register with one call and no human, or sign in with AgentID and an inbox you control. - [Signup](https://app.last-price.ai/sign-up): AgentID, email and Google sign-in on the production app. - [Agent manifest](https://api.last-price.ai/.well-known/agents.json): Registration, supported authentication, scopes and rate limits. - [OpenAPI contract](https://api.last-price.ai/api/openapi): Current API operations and response schemas. - [API reference](https://last-price.ai/api-docs): Human-readable contract. - [Pricing](https://last-price.ai/pricing): Product pricing information. ## Changes Check at the start of a session and before changing integration code. - JSON Feed: https://last-price.ai/changelog/feed.json. Keep the items where `_lastprice.audience` includes `agents`. - RSS: https://last-price.ai/changelog/feed.xml - Page: https://last-price.ai/changelog A browser sign-in is not an API credential. Keep keys private. Use x-api-key for API keys and GET /api/me to discover the credential's workspace. Account restrictions and scope checks apply. Provider directory listing is separate from this site's discovery documents. In the OpenAPI contract, `security: []` does not mean open. Each such operation carries `x-lastprice-auth`: `public` needs no credential, and `session-cookie` works only from a signed-in dashboard browser and answers 401 to any API key or JWT. Workspace administration (creating and deleting workspaces, workspace settings and the workspace LLM key) needs a person signed in to the dashboard, and no API key or OAuth token reaches it. Team administration (members, roles, invitations) works from the dashboard session or from an API key holding the exact team:admin scope, which only a workspace owner or admin can mint, from the dashboard; the next paragraph has its rules. An agent acting for an owner can read its own workspace with GET /api/me, and claim an agent workspace with a key holding workspace:claim. Team administration (members, roles, invitations) also takes an API key holding team:admin by name, sent as x-api-key, acting for the owner or admin who created it in the dashboard. It works only in the key's own workspace and only while that person is still an owner or admin there; it never grants the owner role or a role above theirs, never changes the owner or that person, and only an owner's key can demote or remove an admin. Nobody, an owner included, can demote or remove the workspace owner of record or leave the workspace without an owner, and a change that collides with a concurrent one answers 409 with retryable true. An invitation it sends stays acceptable only while the key and that person still carry that authority. Agent tokens are refused there, and every call, refused ones included, lands in GET /api/audit, readable by owners and admins. Workspace settings and creating or deleting workspaces stay dashboard only. ## When a call fails Every error body keeps its `error` field and any `code` it already had. Optional top-level fields, beside `error`, say what to do next: `hint` (one sentence), `next` (calls that get you unstuck, as a list of `{method, path, description}` steps, with an `id` where a body lists steps you must tell apart), `example` (a minimal valid body), `issues` (each failing field as `{path, message}`), `retry_after` (seconds, equal to the `Retry-After` header) and `limit` (requests per window). - 401: `hint` names the accepted credentials (a JWT as `Authorization: Bearer`, an API key as `x-api-key`) and `next` points at `POST /api/agents/register` (no credential needed) and `POST /api/oauth/token`. A route that takes only a person's credential (agent management, agent keys and inbox, approval decisions) answers a valid API key with a `hint` saying so and an empty `next`: no new key would help. - 400: `validation_failed` lists `issues` and, on the main operations, an `example`. - 400 `invalid_json`: the body did not parse. Sent by `POST /api/api-keys`, `POST /api/commerce/connectors`, `PATCH /api/commerce/connectors/{id}`, `POST /api/commerce/cycle`, `POST /api/compute/batch`, `POST /api/compute/conversation`, `POST /api/compute/price`, `POST /api/costs`, `POST /api/credits`, `POST /api/customers`, `POST /api/disputes`, `POST /api/embed-tokens`, `POST /api/functions`, `POST /api/invoices`, `POST /api/jale/contribute`, `POST /api/jale/contribute/batch`, `POST /api/marketplace/listings`, `PATCH /api/marketplace/listings/{listingId}`, `POST /api/orders`, `POST /api/payments`, `POST /api/price-router`, `POST /api/price-router/verify`, `POST /api/pricing-models`, `POST /api/routing-policies`, `PATCH /api/routing-policies/{id}`, `PATCH /api/usage/events/{id}/outcome`, `PATCH /api/usage/llm/events/{id}/outcome`, `POST /api/webhooks`, `PATCH /api/webhooks/{webhookId}`. Elsewhere such a body can answer with another code, with only `error`, or, on some older routes, a 500. - 403 `insufficient_scope`: `required_scopes` lists what is missing and `hint` says how to get a key that carries it. - 429: wait `retry_after` seconds, then retry. A 429 `quota_exceeded` is a daily limit: it resets after `retry_after` seconds, and `next` lists the ways past it sooner. Where the call can be paid for, a step with `id` `pay_per_call` says how to send it again with an x402 payment (its `header`, `price`, `asset`, `network` and `pay_to`). On a daily compute limit, a step with `id` `day_pass` says how to buy a day pass of extra compute calls (its `calls`, `valid_hours`, `header`, `price`, `asset` and `network`); after buying one, send the refused request again. A step with `id` `claim` says how a person lifts the limit for good.