Authentication
Required headers, permissions, and authentication methods for the integration API.
All integration endpoints require authentication. Use an API key: it is the method intended for integrations, and the examples in this section use it. The endpoints also accept a user token (JWT) — see User token vs API key.
Required header
Each request authenticated with an API key includes the following header:
| Header | Value | Description |
|---|---|---|
x-api-key | rtn_sk_... | API key generated from the administration panel |
curl -X GET BASE_URL/api/integration/activities/tasks \
-H "x-api-key: YOUR_API_KEY"No API key sends the x-tenant-id header: the tenant always comes from the key. Whether the key sends x-project-id depends on its scope — a project key does not need it, a tenant key sends it where the endpoint requires it or to narrow a request to one project. See Key scope.
The API key is shown only once at creation time. If you lose it, you will need to revoke it and create a new one from the administration panel.
Obtaining an API key
Reten Environments
| Environment | Admin Panel | API Base URL |
|---|---|---|
| Development | app-development.reten.ai | https://api-development.reten.ai |
| Staging | app-staging.reten.ai | https://api-staging.reten.ai |
| Production | app.reten.ai | https://api.reten.ai |
Use the admin panel URL to manage API keys and dispatch configurations. Replace BASE_URL in code examples with the API base URL for your environment.
API keys are created from the Reten administration panel by a user with admin role or higher:
- Navigate to Settings → API Keys
- Click Create API Key
- Assign a descriptive name (e.g., "Task Dispatch — YOM")
- Select the required permissions based on the endpoints you will use
- Copy the generated key and store it securely
Permissions per endpoint
Each integration endpoint requires a specific permission on the API key:
| Endpoint | Method | Required permission |
|---|---|---|
/api/integration/activities/tasks | GET | activity:view |
/api/integration/activity-results/tasks | POST | activity-result:submit |
/api/integration/task-result-type-configs | GET | activity:view |
/api/integration/commerces/batch-upsert | POST | commerce:batch-upsert |
/api/integration/operators/batch-upsert | POST | operator:batch-upsert |
/api/integration/routes/batch-upsert | POST | route:batch-upsert |
An API key's permissions are chosen by its owner and must be a subset of the permissions the owner currently holds. On every request, the key's effective permissions are the intersection of its stored set with the owner's current permissions — if the owner loses a permission, the key loses it too; if the owner gains one, the key does not. If you need an additional permission, the key's owner adds it by editing the key's permissions with PUT /api/api-keys/:id/permissions or from Settings → API Keys.
Key scope
Each API key belongs to a single tenant, and the tenant always comes from the key — no key sends x-tenant-id. The key's scope, chosen when the key is created (see Create API Key), decides how the project is chosen on project-scoped and project-optional endpoints.
Project-scoped endpoints work in exactly one project per request. Project-optional endpoints accept x-project-id but do not require it: when it is sent, it narrows the request to that project and is validated as on a project-scoped endpoint. Without it, a read covers the whole tenant and a result takes the project of its activity; a result without activity_id has no activity to take a project from, so it needs the header — without it the API responds 400. A project key always works in its own project.
Project key (scope: "project") | Tenant key (scope: "tenant") | |
|---|---|---|
| Project of each request | Always the key's project | The one named in x-project-id; on a project-optional endpoint without the header, none |
x-project-id on project-scoped endpoints | Not needed. Sending the key's own project is accepted; naming another project responds 403 — La API key pertenece a un proyecto distinto del que declara el header x-project-id. | Required. Without it the API responds 400 — Falta el header obligatorio x-project-id. |
x-project-id on project-optional endpoints | Not needed, as on project-scoped endpoints: naming another project responds 403. A result without activity_id goes to the key's project; a result for an activity of another project responds 404 — Actividad no encontrada. | Optional. With it, the request is narrowed to that project. Without it, a read covers the whole tenant and a result takes the project of its activity; a result without activity_id responds 400 — Falta el header obligatorio x-project-id: un resultado sin activity_id necesita proyecto. |
x-project-id on tenant-level endpoints | Ignored | Ignored |
The integration endpoints split as follows:
| Endpoint | Method | Kind |
|---|---|---|
/api/integration/activities/tasks | GET | Project-optional |
/api/integration/activity-results/tasks | POST | Project-optional |
/api/integration/task-result-type-configs | GET | Tenant-level |
/api/integration/commerces/batch-upsert, /api/integration/operators/batch-upsert, /api/integration/routes/batch-upsert | POST | Tenant-level |
The examples of the integration API only send x-api-key, so they work as written with a project key and with a tenant key. With a tenant key, add the x-project-id header to narrow a call to one project, and always to submit a result without activity_id.
API keys created before projects existed are tenant keys (projectId: null) and follow the tenant key column above: they send x-project-id on project-scoped endpoints and to submit a result without activity_id.
If your system receives activities through dispatch, use a tenant key to submit their results. Dispatch sends the activities of every project of the tenant, and a project key only reaches its own project: with it, the result of an activity of another project responds 404 — Actividad no encontrada.
- If
x-api-keyis invalid or revoked →401 Unauthorizedresponse - If the key does not have the required permission →
403 Forbiddenresponse - Returned data always corresponds to the key's tenant and, when the request has an active project (the key's, or the one in
x-project-id), to that project
User token vs API key
| Feature | JWT (User token) | API Key |
|---|---|---|
| Primary use | Interactive sessions in the app | Programmatic integrations |
| Duration | 15 minutes (access token) | No expiration (or configurable date) |
| Renewal | Automatic via refresh token | Not applicable — the key is permanent |
| Permissions | All permissions from the user's role | Set chosen by the owner, editable at any time; effective = intersection with the owner's current permissions on every request |
x-tenant-id header | Required | Not needed (tenant resolved from the key) |
x-project-id header | Required on project-scoped endpoints; optional on project-optional endpoints (see Key scope) | Project key: not needed. Tenant key: same as a user token |
| Integration endpoints | Accepted | Recommended |
Endpoints under /api/integration/* accept both methods; use an API key for integrations. With a user token, each request sends Authorization: Bearer <access_token> and x-tenant-id; x-project-id follows the same rules as with a tenant key — see Project Context.