Agents and integrations

Connect, referrals and your own endpoint.

Give each of your users a sub-key and balance, earn a markup in USDF, and serve models through the gateway.

On this page

An account becomes a platform with a platform key. The platform key never spends: it mints one sub-key per end user and reads the platform's figures. On the dashboard: Connect.

1. Create the platform key

Under your session. It is shown once, and it cannot call chat. Samples read it from $PLATFORM_KEY.

Create a platform key

curl
curl -X POST https://api.usdf.fi/v1/platform/create \
  -H "Authorization: Bearer $SESSION"

Response

{
  "key_id": "<key_id>",
  "api_key": "sk_…",
  "key_prefix": "<prefix>",
  "role": "platform",
  "note": "Shown once. This key mints sub-keys … it cannot call /v1/chat/completions itself."
}

2. Set your markup

markup_bps is 0 to 5000 basis points of the sheet cost. It is credited to your balance as each request is billed.

Set the markup

curl
curl -X PATCH https://api.usdf.fi/v1/platform \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -H "Content-Type: application/json" \
  -d '{"markup_bps": 250}'

3. Know the limit

Platform calls are limited to — per platform key. A sub-key is an ordinary API key, with the per-key limit: —.

A sub-key is an ordinary API key with its own balance, funded from the end user's own wallet. A wallet is bound to a sub-key only by the wallet's own signature.

1. Ask for the wallet proof

Wallet proof

curl
curl -X POST https://api.usdf.fi/v1/platform/wallet-proof \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -H "Content-Type: application/json" \
  -d '{"end_user_ref": "user-a", "wallet_address": "<end user wallet>"}'

Response

{
  "end_user_ref": "user-a",
  "wallet_address": "<end user wallet>",
  "nonce": "<nonce>",
  "message": "<message the end user signs>",
  "sign": "personal_sign (EIP-191) by wallet_address"
}

2. The end user signs

The end user's wallet signs message with personal_sign. The nonce is single use.

3. Mint the sub-key

Mint a sub-key

curl
curl -X POST https://api.usdf.fi/v1/platform/keys \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "end_user_ref": "user-a",
    "limits": {
      "budget_units": "10000000",
      "rate_limit_rpm": 60,
      "spend_limit_hour_units": "1000000",
      "spend_limit_day_units": "5000000"
    },
    "wallet_address": "<end user wallet>",
    "wallet_nonce": "<nonce>",
    "wallet_signature": "<signature>"
  }'

Response

{
  "key_id": "<sub_key_id>",
  "api_key": "sk_…",
  "key_prefix": "<prefix>",
  "end_user_ref": "user-a",
  "role": "sub",
  "wallet_address": "<end user wallet>",
  …
}

The fields:

FieldRules
end_user_refYour own id for the end user, 1 to 128 characters.
limitsbudget_units, rate_limit_rpm, spend_limit_hour_units, spend_limit_day_units.
wallet_address, wallet_nonce, wallet_signatureOptional. With a wallet, the proof is required, and deposits from that wallet credit the sub-key.

Manage sub-keys with the platform key:

EndpointWhat it does
GET /v1/platform/keysEvery sub-key: balance, held, spent, limits, pause state.
POST /v1/platform/keys/{id}/walletSets the sub-key's wallet, with a new proof.
POST /v1/platform/keys/{id}/withdrawReturns unspent balance to the sub-key's own wallet: amount_units, at least 0.10 USDF.
POST /v1/platform/keys/{id}/revokeRevokes it, once its balance is zero.

Return a sub-key's balance

curl
curl -X POST https://api.usdf.fi/v1/platform/keys/<sub_key_id>/withdraw \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount_units": "1000000"}'

A sub-key's withdrawals: at most 3 open and 10 per day. Its holds include the markup, so 402 insufficient_balance means the balance cannot cover cost plus markup.

GET /v1/platform/usage reports requests, tokens, cost and markup per end user, with days and end_user_ref. /v1/platform/usage.csv is the same as CSV.

Read usage

curl
curl "https://api.usdf.fi/v1/platform/usage?days=30&end_user_ref=user-a" \
  -H "Authorization: Bearer $PLATFORM_KEY"

Your markup earnings are paid in USDF to your account balance, and withdraw like any balance. See Withdraw.

The buy embed lets an end user fund their sub-key from their own wallet, inside your product. Frame /embed/buy?key=<sub_key_id>; it reads GET /v1/platform/embed/{sub_key_id}, which is public. See the embed.

Show that you accept USDF with the badge:

Accepts USDF

Badge HTML

<a href="https://api.usdf.fi/v1/pricing">
  <img src="https://api.usdf.fi/badge.svg" alt="Accepts USDF">
</a>

See Connect for the overview.

Loading…

EndpointWhat it does
GET /v1/referralsYour code, link and earnings. Session, or the account's own API key.
POST /v1/referrals/attachAttaches a referral code to your account. Session.
GET /v1/referrals/termsThe terms above, read live. Public.

Your link is on the dashboard, under Referrals. See Affiliates.

Register an OpenAI-compatible chat completions endpoint, and the gateway routes requests to it beside its other routes. You are credited the upstream cost of every request you serve, at your own price, in USDF.

Your route serves requests paid from a user account's own balance. Requests made with a team key, a platform sub-key or an agent key run on the other routes.

1. Register

POST /v1/providers, under your session. The account needs a linked wallet: earnings are withdrawn to it.

Register an endpoint

curl
curl -X POST https://api.usdf.fi/v1/providers \
  -H "Authorization: Bearer $SESSION" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Compute",
    "slug": "acme",
    "base_url": "https://api.example.com/v1",
    "auth": { "header": "authorization", "value": "Bearer sk-..." },
    "data_policy": { "retains": false, "trains": false, "region": "us" },
    "models": [
      {
        "id": "llama-3.3-70b-instruct",
        "upstream_model": "acme/llama-70b",
        "input_price": 0.08, "output_price": 0.2,
        "context": 65536, "max_output": 8192
      },
      {
        "id": "sp-acme.house-7b", "name": "House 7B",
        "upstream_model": "house-7b",
        "input_price": 0.2, "output_price": 0.6,
        "context": 32768, "max_output": 4096
      }
    ]
  }'

Response, 201, trimmed

{
  "provider": {
    "id": "sp-acme",
    "status": "pending",
    "proof": { "url": "https://api.example.com/.well-known/usdf-provider.txt", "token": "sp-acme:…" },
    "models": [ { "id": "llama-3.3-70b-instruct", "status": "unverified", "serving": false, … }, … ],
    …
  },
  "next": "Serve this token as a line of … then POST /v1/providers/sp-acme/verify: …"
}

The fields:

FieldRules
nameYour endpoint's name.
slug3 to 24 lower-case letters, digits or hyphens; from name when left out. The endpoint's id is sp-<slug>, the provider name on routes, usage rows and receipts.
base_urlhttps:// on port 443 and a public DNS name that resolves to public addresses only. The gateway calls <base_url>/chat/completions.
authThe one header the gateway sends with every request: authorization (the default), api-key or an x- header of your own. The value is sealed before it is stored, and no endpoint returns it.
data_policyretains and trains (booleans) and an optional region. A declaration, shown as one on receipts.
modelsEach with id (a catalog model, or a new one named sp-<slug>.<name>), upstream_model, input_price and output_price in USD per 1M tokens, context and max_output.

For a catalog model, your price must be at least 5% below the cheapest route the price sheet lists for it, in every rate it bills. Otherwise the registration is refused with 400 priced_above_sheet. Callers keep paying the sheet's price. A new model of your own gets a sheet entry at your price plus the published markup.

2. Prove control of the origin

Serve provider.proof.token from the answer as a line of its own, answering 200 itself, with no redirect:

Proof file

https://api.example.com/.well-known/usdf-provider.txt

<provider.proof.token, on a line of its own>

3. Ask for the check

Once the file is in place, ask the gateway to read it. It then sends each model one real streamed request; a model serves once its check passes.

Verify the endpoint

curl
curl -X POST https://api.usdf.fi/v1/providers/sp-acme/verify \
  -H "Authorization: Bearer $SESSION"

Response, 202, trimmed

{
  "provider": { "id": "sp-acme", "status": "active", … },
  "proof": { "ok": true, "error": null },
  "checks": "started",
  "next": "…"
}

4. Serve and earn

EndpointWhat it does
GET /v1/providers/meYour endpoints, each route's check status, and your earnings.
POST /v1/providers/me/withdrawWithdraws the balance to the linked wallet, as USDF: {"units": "…"}.
DELETE /v1/providers/{id}Stops the endpoint's routes. Recorded earnings stay.
GET /v1/providersThe public list of active providers with a verified route.

An earning is credited once it is a day old. A catalog model's route takes the model's default traffic once it is approved. Until then it serves requests that name it with provider.only. Refusals are on Errors.

Next: the USDF token