Skip to main content
Rezolve Ai
Guides

Partner API

Onboard your own customers as tenants, provision their API keys, and call Rezolve Ai on their behalf.

The Partner API is for platforms that offer Rezolve Ai inside their own product. Instead of asking each of your customers to sign up and create a key in the console, you create a tenant for each one through the API, and either mint the tenant its own key or name the tenant on each call you make with yours.

Partner access is turned on per account by Rezolve Ai. Ask your account contact to enable it. Until it is on, the endpoints below answer 403 PARTNER_REQUIRED.

How it fits together

  • Your partner account is an ordinary Rezolve Ai account with partner access. It owns every tenant you create, and its credit balance pays for all of them.
  • A tenant is one of your customers. Each tenant is a project on your account, so its products, jobs, generated content and usage are kept apart from every other tenant's.
  • Your partner key is an account-wide live key on your partner account with the admin scope. Create it under Settings, Developer console, Keys, and keep it on your servers. It is the only key that can create and manage tenants.

Every tenant endpoint takes your partner key and is refused for any other key, including a tenant's own.

Create a tenant

Send POST /api/v1/tenants with a name, and your own id for the customer in externalId:

curl -X POST "https://ace.authoritas.com/api/v1/tenants" \
  -H "Authorization: Bearer <your-partner-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Outdoor",
    "externalId": "457afb25-a978-4275-80b1-cc64a9be9f13",
    "config": { "targetLanguage": "en-GB", "brandVoice": { "tone": "warm", "targetAudience": "hikers" } },
    "key": { "env": "live" }
  }'

The 201 response carries the tenant and, because key was sent, its first key with the secret in data.key.key. Store the secret now: it is returned only this once.

Creating is idempotent on externalId. If a tenant with that id already exists, you get it back with 200 and "created": false, and no second key is minted. So it is safe to call this whenever you meet a customer, without asking first whether you have before. To find a tenant later by your own id, call GET /api/v1/tenants?externalId=<your-id>.

Call the API for a tenant

There are two ways, and you can use both.

Name the tenant on each call. Send your partner key and the tenant's id in the X-Tenant-Id header. The call then runs in that tenant exactly as if it had been made with a key pinned to it:

curl -X POST "https://ace.authoritas.com/api/v1/enrichment/rules" \
  -H "Authorization: Bearer <your-partner-key>" \
  -H "X-Tenant-Id: <tenant-id>" \
  -H "Content-Type: application/json" \
  -d '{ "source": { "type": "inline", "products": [{ "id": "sku-1", "title": "Trail running shoe" }] } }'

This suits a gateway that forwards its users' requests: you keep one secret, and the tenant is chosen per call. The header is accepted on every endpoint that takes an API key. A key that is not a partner's gets 403 PARTNER_REQUIRED, an id that is not one of your tenants gets 404 TENANT_NOT_FOUND, and a tenant key that names a different tenant gets 403 PROJECT_SCOPE_MISMATCH.

Use the tenant's own key. A key minted for a tenant works only for that tenant, with no header needed. Use one when a separate system calls for that customer, or when you want to revoke one customer's access without touching the others.

Either way, leave projectId out of request bodies. The tenant is the project.

Manage a tenant's keys

MethodPathDoes
GET/tenants/{id}/keysList the tenant's keys, without secrets.
POST/tenants/{id}/keysMint a key. Body: optional name, env (live or test), scopes, rateLimitPerMinute, expiresAt.
POST/tenants/{id}/keys/{keyId}/rotateMint a successor. The old key keeps working for graceHours (default 24).
DELETE/tenants/{id}/keys/{keyId}Revoke a key. It stops working at once.

A tenant key gets enrichment:read, enrichment:write and utils:read unless you ask for other scopes. It may also hold feeds:read, feeds:write, ratings:read and ratings:write. It can never hold admin or a webhooks scope, because webhook subscriptions belong to your whole account rather than to one tenant.

Set a tenant's defaults

config on create, or on PATCH /api/v1/tenants/{id}, stores defaults for the tenant's enrichment calls: brandVoice, targetLanguage, creativityLevel, contentTypes and reviewQueue. A call that leaves a field out uses the tenant's default, and a field the call sends always wins. Brand voice merges field by field, so a call that sends only a tone keeps the tenant's audience and language.

config on PATCH replaces the stored defaults as a whole. Send {} to clear them.

Job output is not written into a tenant's review queue unless you set reviewQueue to true.

Suspend or delete a tenant

PATCH /api/v1/tenants/{id} with { "status": "suspended" } switches a tenant off: calls with its keys, or naming it in X-Tenant-Id, are refused with 403 TENANT_SUSPENDED until you send { "status": "active" }. Nothing is deleted.

DELETE /api/v1/tenants/{id} deletes the tenant with everything in it, and its keys stop working. It cannot be undone.

Billing and usage

Every tenant's work is charged to your partner account's credits, at the same rates as any other call. See Credits and usage. Each charge is recorded against the tenant it was for, so you can bill your own customers:

  • GET /api/v1/tenants/{id}/usage?from=&to= returns the credits charged for the tenant, its requests and errors, and its jobs, over a window of up to 93 days. It defaults to the current calendar month (UTC). Request counts go back 30 days.
  • GET /api/v1/usage made for a tenant also returns data.tenant.creditsUsedThisPeriod.

When your balance runs out, live calls for every tenant are refused with 402 INSUFFICIENT_CREDITS.

Test keys

Mint a tenant key with "env": "test", or call with an account-wide test key and X-Tenant-Id, to run without spending credits. Test calls share one monthly allowance across your partner account, which can be raised for partners. Ask your account contact.

Webhooks

Subscribe once, with your partner key, as described in the webhooks guide. Every delivery for a tenant's job carries the tenant's id in project_id, so you can route it to the right customer.

Errors

CodeStatusWhen
PARTNER_REQUIRED403The account is not a partner, or a tenant endpoint was called with a key other than the partner key.
TENANT_NOT_FOUND404No such tenant on this account.
TENANT_SUSPENDED403The tenant is suspended.
TENANT_LIMIT_REACHED409The account holds as many tenants as it is allowed.
PROJECT_SCOPE_MISMATCH403A tenant's key named a different tenant in X-Tenant-Id.

See the Tenants API reference for every request and response shape.

On this page