Console
Billing

Partner accounts

Create and fund accounts for your own customers.

A partner is an organization that creates RouterPlus accounts for its own customers. Each account is an organization of its own. The partner funds each account from its balance and earns a share of the account's spend.

To become a partner, contact RouterPlus. RouterPlus sets your revenue share and turns the partner API on for your organization.

bash
curl https://dev2-api.routerplus.com/v1/partner/accounts \
  -H "Authorization: Bearer $PARTNER_MANAGEMENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"external_id": "cust-1042", "name": "Acme Corp", "credit_usd": 25}'

Authentication

The partner API uses a management key of the partner organization: Authorization: Bearer tm_mk_.... Create one with POST /v1/management-keys (see the management API). Every route is served under /v1/... and /api/v1/....

  • A partner sees and changes only its own accounts. An account of another partner returns 404.
  • A management key of an organization that is not a partner returns 403 not_a_partner.
  • An account's own keys cannot call the partner API.

Routes

RouteDoes
POST /v1/partner/accountsCreates an account. Returns 201.
GET /v1/partner/accountsLists every account.
GET /v1/partner/accounts/{external_id}Reads one account.
PATCH /v1/partner/accounts/{external_id}{"disabled": true} or {"disabled": false}.
POST /v1/partner/accounts/{external_id}/credits{"usd": n}. Moves credit to the account.
POST /v1/partner/accounts/{external_id}/keys{"name"?}. Creates another inference key. Returns 201.
GET /v1/partner/earnings?period=YYYY-MMSpend and revenue share per account for one month.

Each account shows balance_usd and month_to_date_spend_usd, its spend since the start of the current UTC month.

Create an account

FieldTypeNotes
external_idstringYour own id for the customer. 1 to 128 letters, digits or . _ : @ -. Unique among your accounts.
namestringThe account's organization name, 1 to 100 characters.
credit_usdnumberOptional. Credit to move from your balance to the account, 0 to 10,000.

The answer is 201:

json
{
  "data": {
    "external_id": "cust-1042",
    "org_id": "6c1f0d1e-2a35-4a3e-9a51-0f4c2d7b9e10",
    "name": "Acme Corp",
    "disabled": false,
    "balance_usd": 25,
    "month_to_date_spend_usd": 0,
    "workspace_id": "0b8e3f52-7c41-4d55-8f0a-3e2d9a6c1b77",
    "created_at": "2026-10-31T12:00:00.000Z"
  },
  "key": "tm_vk_...",
  "key_id": "…",
  "management_key": "tm_mk_...",
  "management_key_id": "…"
}

The account gets a default workspace and two keys:

  • key is an inference key. Give it to your customer, or call models with it for them.
  • management_key is a management key for the account's own organization. With it the account can create keys, set guardrails and read its activity.

The answer shows each raw key once. RouterPlus stores only a hash. Keep both keys safe.

An external_id that you already use returns 409.

Move credit to an account

Send {"usd": 10} to POST /v1/partner/accounts/{external_id}/credits.

  • The amount is above 0 and at most 10,000.
  • RouterPlus takes the amount from your balance and adds it to the account's balance in one step. The answer gives the account, and your new balance in transfer.partner_balance_usd.
  • When your balance is less than the amount, the answer is 402 insufficient_balance and no credit moves. The same rule applies to credit_usd on create: the account is not created.
  • Credit on an account cannot move back to the partner.

Create another key

POST /v1/partner/accounts/{external_id}/keys returns 201 with a new inference key in key, shown once. The key is in the account's default workspace.

Disable an account

{"disabled": true} turns off every key of the account: its inference keys and its management keys. Requests with those keys get 401. You cannot create keys for a disabled account.

{"disabled": false} turns on the keys that the disable turned off. A key that was already off before the disable stays off. A key can take up to 5 seconds to work again.

Earnings

period is a UTC month as YYYY-MM. Without it, the current month.

json
{
  "period": "2026-10",
  "revenue_share_percent": 20,
  "data": [
    { "external_id": "cust-1042", "org_id": "…", "spend_usd": 412.5, "revenue_share_usd": 82.5 }
  ],
  "totals": { "spend_usd": 412.5, "revenue_share_usd": 82.5 }
}
  • spend_usd is the account's usage at RouterPlus prices in the month. Usage on the account's own provider keys is not in it.
  • revenue_share_usd is spend_usd times your revenue share, rounded to a millionth of a dollar.
  • totals adds up all accounts.

If RouterPlus set a markup for you, each account also shows markup_usd, and the answer shows markup_percent and markup_note. The markup is a reporting field: the amount you can charge your customers on top. RouterPlus bills your accounts at its own prices.

Audit

Every change writes an audit row on your organization and on the account. Read your rows with GET /v1/audit.

Errors

StatusTypeWhen
400invalid_requestA field is missing, unknown or out of range.
401unauthorizedNo management key, or the key is not valid.
402insufficient_balanceYour balance is less than the credit to move.
403not_a_partnerThe key's organization is not a partner.
403partner_disabledRouterPlus turned off the partner API for your organization.
404not_foundNo account with this external_id among your accounts.
409conflictThe external_id is already in use.
409account_disabledYou asked for a key on a disabled account.

For agents: /docs/partners.md and /llms.txt