Build

API reference.

The OpenAI-compatible endpoints, their parameters, and what each response carries.

On this page

The base URL is https://api.usdf.fi/v1. Requests and responses follow the OpenAI chat completions format. Messages and stateless Responses are also served.

Two ways to pay for a request:

  • No account: send the same body with no key to the same path under https://api.usdf.fi/x402 and pay per request in USDF.
  • A prepaid balance: send Authorization: Bearer sk_… to the path below.

The model endpoints and the reads around them, with what each needs:

EndpointWhat it doesAuth
POST /v1/chat/completionsChat, streaming, tools and vision. Also submits batch jobs.Key, or pay per request under /x402
POST /v1/messagesMessages format. Any available chat model id; x-api-key or Bearer key. Base URL https://api.usdf.fi.Key
POST /v1/messages/count_tokensCount input tokens for a Messages request.Key
POST /v1/responsesStateless Responses. Send conversation history in input.Key
POST /v1/completionsLegacy text completions.Key, or pay per request under /x402
POST /v1/embeddings, /images/generations, /images/edits, /audio/transcriptions, /audio/speech, /rerank, /videos/generationsThe other modalities. See Modalities.Key, or pay per request under /x402
GET /v1/modelsThe models that serve right now.None
GET /v1/pricingThe full price sheet, every listed model.None
GET /v1/pricing/sheets, /{version}Every price sheet ever served.None
GET /v1/pricing/observationsUpstream list prices as observed.None
GET /v1/catalog, /signer, /signatureThe signed model catalog.None
GET /v1/batches/{id}, /resultA batch job, and its result.Key
GET /v1/toolsTools, their prices and input schemas.None
POST /v1/tools/{id}Runs one tool on the balance.Key
GET /v1/receiptsYour latest receipts.Key or session
GET /v1/receipts/{id}One receipt, with its place in the usage log.The key that made the request
GET /x402/v1/receipts/{id}The public receipt of any request.None
GET /v1/limitsEvery rate limit, live.None
GET /v1/statusService status and open incidents.None
GET /healthThe gateway's own health.None

Public data, with no key. Each one backs a page of the site:

EndpointReturnsOn the site
GET /v1/ecosystemThe figures the site quotes, each with the endpoint it is read from.Docs
GET /v1/holders/rewardsUSDF Rewards: the terms and the rate, every hour.Earn
GET /v1/privacy/attestationThe attestation report behind private inference.Private inference

Every limit these reads share is in Rate limits. Account, agent, platform and receipt endpoints are on their own pages: Accounts and keys, Agents, Platforms and providers and Receipts. Every endpoint, token and receipt reads included, is in the API reference.

POST /v1/chat/completions takes the standard body. Samples use <model>.

Chat completion

curl https://api.usdf.fi/v1/chat/completions \
  -H "Authorization: Bearer $USDF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model>",
    "messages": [{"role": "user", "content": "Hello"}],
    "max_tokens": 256
  }'

Response, trimmed

x-request-id: <request_id>
x-cost-units: <units>

{
  "id": "<request_id>",
  "object": "chat.completion",
  "model": "<model>",
  "choices": [{ "index": 0, "message": { "role": "assistant", "content": "…" }, "finish_reason": "stop" }],
  "usage": { "prompt_tokens": …, "completion_tokens": …, "total_tokens": … },
  "receipt": { "request_id": "<request_id>", "status": "ok", "cost": { … }, … }
}

The parameters the gateway reads:

ParameterTypeRequiredNotes
modelStringYesA model id. Suffixes such as :cheapest are in Routing.
messagesArrayYesNon-empty. Images go in message content.
max_tokens, max_completion_tokensIntegerNoPositive, up to the model's max_output. Sets the hold. Above it: 400 context_length_exceeded.
streamBooleanNoServer-sent events.
stream_options.include_usageBooleanNoA final usage chunk.
temperatureNumberNo0 to 2.
nIntegerNoMust be 1.
tools, tool_choice, parallel_tool_callsArray, string or objectNoFunction calling.
response_formatObjectNoJSON mode or a JSON schema.
reasoning_effortStringNoFor reasoning models.
top_p, top_k, min_p, stop, seed, frequency_penalty, presence_penalty, repetition_penalty, logit_bias, logprobs, top_logprobs, userAs OpenAINoPassed through to the provider.
providerObjectNoRouting and privacy. See Provider preferences.
batch, webhook_urlBoolean, stringNoSubmit as a job. See Batch jobs.
  • The deprecated functions and function_call are refused with 400 unsupported_parameter. Use tools.
  • Fields that would change what the provider bills are dropped.
  • Up to 16 images per request. More gets 400 too_many_images.
  • The response id is the request id, also in the x-request-id header. A response that is not streamed carries the cost in x-cost-units; a stream carries it in its receipt line.

How the hold is sized

The prompt is held at two bytes per token, plus eight tokens per message and 16 per request, plus max_tokens. A model with long-context rates is held at one byte per token, so the hold never lands in a cheaper tier.

Without max_tokens, the model's default output budget is held, shrinking to what the balance covers. The charge is the provider's reported usage; the rest of the hold is released.

Set "stream": true for server-sent events in the standard chunk format.

The order of events:

Server-sent events

data: {"id":"<request_id>","object":"chat.completion.chunk",…}

data: {"id":"<request_id>","choices":[],"usage":{…}}

: receipt {"request_id":"<request_id>","cost":{"units":"…","usd":"…","usdf":"…"},…}

data: [DONE]

The receipt arrives as a comment line just before [DONE]. Standard clients drop comment lines, so read the receipt by id afterwards with GET /v1/receipts/{id}. Every chunk's id is the request id.

Stream, then read the receipt

curl -N https://api.usdf.fi/v1/chat/completions \
  -H "Authorization: Bearer $USDF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model>",
    "stream": true,
    "stream_options": {"include_usage": true},
    "messages": [{"role": "user", "content": "Hello"}]
  }'

POST /v1/completions serves only models whose endpoints include completions. prompt is a string, or an array of one string.

Text completion

curl
curl https://api.usdf.fi/v1/completions \
  -H "Authorization: Bearer $USDF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model>",
    "prompt": "The capital of France is",
    "max_tokens": 16
  }'

GET /v1/models lists what serves now. GET /v1/pricing is the full sheet, every listed model with its prices and routes.

The fields of GET /v1/pricing:

FieldMeaning
version, unitThe sheet's version and its default unit.
rate_lockdays and valid_until: how long the sheet's rates are promised.
models[].id, name, owned_byThe model id to send, its name and its maker.
modality, unitWhat the model does, and what its price is per.
endpointsWhere it serves: chat, completions, embeddings and others.
context, max_outputThe context window and the largest output.
priceinput, output, cached_input, cache_write_5m, cache_write_1h, the batch rates batch_input, batch_output, batch_cached_input, batch_cache_write_5m, batch_cache_write_1h, and long_context with its threshold.
price_privateThe private-tier rate.
available, rate_locked_untilWhether it serves now, and how long its price is promised.
routes[]Each provider route, with enabled and its data_policy.

Each price sheet promises its rates for 30 days. Every sheet ever served is at GET /v1/pricing/sheets, and the signed catalog at GET /v1/catalog. Browse them on Models.

Compute locks

A compute lock fixes your price on a block of one model for a month. Each series is a token: one whole token is a million tokens of its model at the locked price, until the month ends. GET /v1/locks has the rules and, signed in, each series with its book.

With one of your account's keys or your session, POST /v1/locks/quote prices a buy, and POST /v1/locks/orders buys at market, places a limit order, or sells what you hold. Your requests for that model then use the lock first: the series' provider serves them, their tokens burn at the locked price, and the receipt names the series. GET /v1/locks/mine lists your holdings, orders and uses, and a holding can be withdrawn to your linked wallet.

A batch job runs at the upstream's batch rate. Submit it with a :batch model suffix or "batch": true, without stream. Add webhook_url to be told when it ends.

A job runs on a model whose price carries batch_input in GET /v1/pricing.

Submit a job

curl
curl https://api.usdf.fi/v1/chat/completions \
  -H "Authorization: Bearer $USDF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model with batch rates>:batch",
    "messages": [{"role": "user", "content": "Hello"}],
    "max_tokens": 256,
    "webhook_url": "https://example.com/usdf-hooks"
  }'

Response, 202

{
  "object": "batch.job",
  "id": "batch_…",
  "status": "submitted",
  "rate": "batch",
  "hold": { "units": "<units>", "usd": "<usd>", "usdf": "<usdf>" },
  "price": { … },
  "poll": "https://api.usdf.fi/v1/batches/batch_…",
  "result": "https://api.usdf.fi/v1/batches/batch_…/result"
}

Poll the job, then fetch its result: the completion and its receipt, which settles like every other request. Results return within 24 hours. The result is kept 7 days, then answers 410.

Poll and fetch

curl
curl https://api.usdf.fi/v1/batches/<batch id> \
  -H "Authorization: Bearer $USDF_API_KEY"

curl https://api.usdf.fi/v1/batches/<batch id>/result \
  -H "Authorization: Bearer $USDF_API_KEY"

How a job ends:

StatusMeaningCharged
doneThe result is ready.Yes, at the batch rates
failedThe upstream failed it. Its result answers 409 batch_failed.No
expiredThe upstream did not finish in time. 409 batch_expired.No

The hold is taken at the standard rate and the charge is made at the batch_* rates when the result arrives.

A job is refused, and nothing is charged, in these cases:

CaseError
The model has no batch rates400 batch_unavailable
The body asks for stream400 batch_unavailable
The key is in no-logs mode: a job's result is stored until fetched400 batch_unavailable
The request asks for the private tier, or the key is private tier400 private_batch_unavailable
The request is paid per request400 batch_unavailable
The gateway is not taking jobs right now503 batch_unavailable, with Retry-After

GET /v1/tools is public. Each tool lists its price (flat per call, or a base plus a price per result), its enabled flag, and its input_schema.

POST /v1/tools/{id} with a key runs one. The body is the tool's input. A call takes a hold, charges what it cost plus 5% at most, with no minimum, and writes a receipt. A call the tool's upstream refused or never answered costs nothing; one that failed after the upstream answered is charged what the upstream billed for it. A call to a tool whose enabled is false is refused with 409 tool_unavailable before any hold.

web.search and web.scrape send the query or the page to a search service that keeps its own records, so they run for calls that opt in to retention: "provider": {"allow_retention": true} in the input, or the key's or the account's opt-in. A call without it is refused with 409 retention_required before any hold.

The tools, read live:

ToolPriceWhat it does

The sample sends the required fields of the tool's input_schema.

Call a tool

curl
curl https://api.usdf.fi/v1/tools/<tool id> \
  -H "Authorization: Bearer $USDF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

The headers the gateway reads and sends:

HeaderDirectionMeaning
AuthorizationRequestA key, a session, a read token, or Payment for MPP.
Content-TypeRequestapplication/json, or multipart/form-data for uploads.
Idempotency-KeyRequestMakes an agent's fund or pay call safe to repeat.
x-approval-idRequestReleases a request an agent's owner approved.
x-erc8004-agentRequestNames the ERC-8004 agent behind a paid request.
PAYMENT-SIGNATURERequestAn x402 payment.
x-request-idResponseThe request id, also the receipt id.
x-cost-unitsResponseWhat the request cost, in units, on a response that is not streamed. A chat or text completion paid per request carries receipt.paid instead.
PAYMENT-REQUIREDResponseThe x402 payment requirements, on a 402.
WWW-Authenticate: PaymentResponseThe MPP challenges, on a 402.
PAYMENT-RESPONSEResponseThe settled x402 payment.
Payment-ReceiptResponseThe settled MPP payment.
Retry-AfterResponseOn a 429 or 503: how many seconds to wait.

Two public reads show how the gateway is doing:

EndpointReturns
GET /healthok, with the state of the chain, the database and the upstreams.
GET /v1/statusThe service's state and any open incidents.
curl https://api.usdf.fi/health

Next: embeddings, images, audio, rerank and video

Foundry documentation