Control API

Customer accounts and key controls through one API.

Access

Send a scoped reseller control key as a Bearer token to https://api.urouter.net/control/v1. Control keys cannot run inference, create additional control keys or add arbitrary credit.

Create a managed customer

Supply your own external_id. It’s unique within your integration, so repeating it returns the same customer. An email address or Telegram identity alone can’t claim an existing account.

curl https://api.urouter.net/control/v1/customers \
  -H "Authorization: Bearer $UROUTER_CONTROL_KEY" \
  -H "Content-Type: application/json" \
  -d '{"external_id":"customer-8842"}'

Create and manage inference keys

POST /control/v1/customers/{customerId}/keys accepts name, models, operations, lifetime_limit, daily_limit, monthly_limit, expires_at and mask_secrets. USD limits are decimal strings or null; expiry is ISO 8601 or null. GET lists metadata. PATCH changes only supplied fields. POST /keys/{keyId}/rotate replaces the secret while preserving the logical key. DELETE revokes it. See OpenAPI for exact bounds.

curl https://api.urouter.net/control/v1/customers/$CUSTOMER_ID/keys \
  -H "Authorization: Bearer $UROUTER_CONTROL_KEY" \
  -H "Idempotency-Key: $OPERATION_UUID" \
  -H "Content-Type: application/json" \
  -d '{"name":"App","daily_limit":"5","mask_secrets":false}'

Retry without duplicating key changes

Use a new UUID Idempotency-Key for each intended key change. Reusing it returns HTTP 409 without repeating the change or showing the secret again. Check /control/v1/operations/{idempotencyKey}: applied includes resource_id. If you lost the secret, check the key’s metadata before rotating it with a new operation ID. Don’t blindly retry an operation that was accepted but hasn’t been applied.

Balance and usage

GET /control/v1/customers/{id} returns the exact USD balance. Filter /usage by model, state or inclusive UTC from/to dates, and use its opaque cursor for pagination. Totals cover all matching requests. Use /requests/{requestId} for one request owned by that customer. Inference keys can read only their own logical key’s requests at /v1/requests/{id}.

Signed events

GET /control/v1/events?cursor=0 returns up to 100 events and next_cursor. Verify HMAC-SHA256 using the control key and timestamp + a period + the exact response body. Compare the result with the sha256= digest in X-Urouter-Event-Signature. Reject a response if X-Urouter-Event-Timestamp differs from the current time by more than five minutes. Deduplicate by event id and save next_cursor. You can safely read a page again. Poll for events; outbound webhooks aren’t enabled.

Permissions

The control scopes are customers.read, customers.create, keys.read, keys.manage, usage.read and events.read. Revoking a token or integration removes access immediately. Key changes also check customer grants inside the write transaction.

Funding

Funding controls stay disabled until payment and usable-funds receipts are verified. There’s no arbitrary-credit endpoint, and customers aren’t given payment instructions yet. Balances can only pay for API usage.

Schema

/openapi.json covers released request fields, authentication, errors and lifecycle. Paid inference and funding aren’t listed as available.