Provider keys, limits and cooldowns
Store the API key of a model provider, check that it works, set its rate limits and take it out of use for a while.
A provider connection is the API key of a model provider, stored in Slen. A call to a model reaches the provider through a connection. The operations of this page store a key, check it, limit it, park it and report how it behaved. The console shows the same connections on Connections.
The secret
The key of the provider is written and never read back. No answer carries it: a connection shows secret_configured and, in secret_last_four, the last four characters of the key.
Send the key as api_key when you create a connection. To replace it, send a new api_key to the update. Creating a connection does not call the provider, so run the test to learn whether the key works.
Project and organization
A connection belongs to one project or to the whole organization. A connection of the organization has project_id set to null, and every project may send calls through it.
An API key acts in its own project.
It lists and reads the connections of its project and of the organization.
It creates a connection in its project. Say so with
scopeset toproject: a request that names no project asks for a connection of the organization, and answers403with the codeproject_access_restricted.It cannot change a connection of the organization. A write to one — update, enable, disable, delete, test, limits, cooldown — answers the same
403.
A connection of another project, or one that does not exist, answers 404 with the code provider_connection_not_found.
Status and health
A connection has two states.
status is stored: active, disabled or invalid_credentials. Only an active connection takes calls. You set disabled and active by disabling and enabling, or with status in the update. Slen sets invalid_credentials when the provider rejects the key of an active connection, and sets active again when a new key is stored or a test succeeds. A disabled connection stays disabled whatever a test finds and whatever key is stored: only your own request puts it back in use — enabling it, or the update with status set to active.
health_status is computed for every answer. It is the first of these that applies: disabled, invalid_credentials, cooldown, degraded, healthy. degraded says that too many of the recent attempts through the connection failed, and error_rate is the share of them that failed.
Deleting
A deleted connection is kept. It gets deleted_at, becomes disabled and leaves every pool it was in. The list leaves it out unless you send include_deleted=1. Enabling a deleted connection restores it, without its place in the pools. Enabling is the only way back: status in the update does not undo a deletion.
Deleting the last enabled connection of a pool is refused: 409 with the code connection_in_use.
The test
The test asks the provider for its list of models with the stored key, which costs no tokens. It records the result on the connection: last_health_check_at, last_health_latency_ms, and the status invalid_credentials when the key of a connection that is not disabled is rejected.
When the provider answers that the key is rate limited, ok is still true: the key is valid, and rate_limited says the rest.
The test takes six calls a minute from one API key. The next call answers 429 with the code rate_limit_exceeded.
Limits and cooldown
A row of limits is for one model. A row without model is the default of the whole connection. The update writes each row the body names and leaves the other rows as they are. A row is written whole: a limit the row does not name is cleared, and a row that names no limit is removed.
A cooldown takes the connection out of use for duration_seconds. A second cooldown can make a running one longer and never shorter. While a cooldown runs, cooldown_until says when it ends. Releasing ends every running cooldown of the connection, the ones Slen started itself too.
Operations
List provider connections
GET /v1/provider-connections
- Scope:
management:read
Mutations on this group are audited.
Parameters
| Parameter | Description |
|---|---|
limit optionalquery | Page size (default 30).
|
cursor optionalquery | The |
provider optionalquery |
|
environment optionalquery |
|
status optionalquery |
|
include_deleted optionalquery |
|
project optionalquery |
|
Responses
One cursor page of connections
{
"data": [
{
"provider_connection_id": "74438200973594624",
"organization_id": "74438200973594624",
"project_id": "74438200973594624",
"provider": "openai",
"name": "string",
"environment": "production",
"region": "string",
"provider_organization_id": "74438200973594624",
"provider_project_id": "74438200973594624",
"status": "active",
"health_status": "healthy",
"cooldown_until": "2026-10-02T09:30:00Z",
"error_rate": "string",
"secret_last_four": "string",
"secret_configured": true,
"last_health_check_at": "2026-10-02T09:30:00Z",
"last_health_latency_ms": 1,
"deleted_at": "2026-10-02T09:30:00Z",
"created_at": "2026-10-02T09:30:00Z",
"updated_at": "2026-10-02T09:30:00Z"
}
],
"meta": {
"limit": 1,
"next_cursor": "string"
}
}Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 422 | Validation failure or a semantically impossible request. Field-level validation from the framework answers |
Headers
X-Request-Id
The body of every error is the error envelope.
Store a provider credential
POST /v1/provider-connections
- Scope:
management:write
The secret is never returned by any endpoint — only secret_last_four and secret_configured.
The connection belongs to the caller's organization. A project_id outside it or out of the caller's reach, or an organization_id other than the caller's, answers 404 (project_not_found / organization_not_found) and stores nothing — the same answer as an id that does not exist.
scope names the side instead of a raw id: project is the active project, organization (also the default without scope and project_id) is no project and needs a caller that reaches every project (403 project_access_restricted). scope together with project_id is 422.
Request body
{
"organization_id": "74438200973594624",
"project_id": "74438200973594624",
"scope": "organization",
"provider": "openai",
"name": "string",
"api_key": "string",
"secret": "string",
"environment": "production",
"region": "string",
"provider_organization_id": "74438200973594624",
"provider_project_id": "74438200973594624"
}Responses
The created connection
{
"data": {
"provider_connection_id": "74438200973594624",
"organization_id": "74438200973594624",
"project_id": "74438200973594624",
"provider": "openai",
"name": "string",
"environment": "production",
"region": "string",
"provider_organization_id": "74438200973594624",
"provider_project_id": "74438200973594624",
"status": "active",
"health_status": "healthy",
"cooldown_until": "2026-10-02T09:30:00Z",
"error_rate": "string",
"secret_last_four": "string",
"secret_configured": true,
"last_health_check_at": "2026-10-02T09:30:00Z",
"last_health_latency_ms": 1,
"deleted_at": "2026-10-02T09:30:00Z",
"created_at": "2026-10-02T09:30:00Z",
"updated_at": "2026-10-02T09:30:00Z"
}
}Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. | |
| 422 | Validation failure or a semantically impossible request. Field-level validation from the framework answers |
Headers
X-Request-Id
The body of every error is the error envelope.
Read one connection
GET /v1/provider-connections/{id}
- Scope:
management:read
Parameters
| Parameter | Description |
|---|---|
id requiredpath | Snowflake identifier, as a string.
|
Responses
The connection
{
"data": {
"provider_connection_id": "74438200973594624",
"organization_id": "74438200973594624",
"project_id": "74438200973594624",
"provider": "openai",
"name": "string",
"environment": "production",
"region": "string",
"provider_organization_id": "74438200973594624",
"provider_project_id": "74438200973594624",
"status": "active",
"health_status": "healthy",
"cooldown_until": "2026-10-02T09:30:00Z",
"error_rate": "string",
"secret_last_four": "string",
"secret_configured": true,
"last_health_check_at": "2026-10-02T09:30:00Z",
"last_health_latency_ms": 1,
"deleted_at": "2026-10-02T09:30:00Z",
"created_at": "2026-10-02T09:30:00Z",
"updated_at": "2026-10-02T09:30:00Z"
}
}Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. |
Headers
X-Request-Id
The body of every error is the error envelope.
Update a connection or rotate its secret
PATCH /v1/provider-connections/{id}
- Scope:
management:write
A new key (api_key) lifts the auth_error pause and an invalid_credentials verdict back to active; it never switches on a disabled or deleted connection.
A connection of no project (the organization's) is written only by a caller that reaches every project; an API key or a member of selected projects hears 403 project_access_restricted.
Parameters
| Parameter | Description |
|---|---|
id requiredpath | Snowflake identifier, as a string.
|
Request body
{
"name": "string",
"status": "active",
"api_key": "string",
"secret": "string",
"environment": "production",
"region": "string",
"provider_organization_id": "74438200973594624",
"provider_project_id": "74438200973594624"
}Responses
The updated connection
{
"data": {
"provider_connection_id": "74438200973594624",
"organization_id": "74438200973594624",
"project_id": "74438200973594624",
"provider": "openai",
"name": "string",
"environment": "production",
"region": "string",
"provider_organization_id": "74438200973594624",
"provider_project_id": "74438200973594624",
"status": "active",
"health_status": "healthy",
"cooldown_until": "2026-10-02T09:30:00Z",
"error_rate": "string",
"secret_last_four": "string",
"secret_configured": true,
"last_health_check_at": "2026-10-02T09:30:00Z",
"last_health_latency_ms": 1,
"deleted_at": "2026-10-02T09:30:00Z",
"created_at": "2026-10-02T09:30:00Z",
"updated_at": "2026-10-02T09:30:00Z"
}
}Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. | |
| 422 | Validation failure or a semantically impossible request. Field-level validation from the framework answers |
Headers
X-Request-Id
The body of every error is the error envelope.
Soft-delete a connection
DELETE /v1/provider-connections/{id}
- Scope:
management:write
A connection of no project (the organization's) is written only by a caller that reaches every project; an API key or a member of selected projects hears 403 project_access_restricted.
Parameters
| Parameter | Description |
|---|---|
id requiredpath | Snowflake identifier, as a string.
|
Responses
Deleted
No body
Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. | |
| 409 | State conflict: idempotency clash, stale draft, illegal transition; the last owner of an organization ( |
Headers
X-Request-Id
The body of every error is the error envelope.
Let the gateway spend through this connection again
POST /v1/provider-connections/{id}/enable
- Scope:
management:write
A connection of no project (the organization's) is written only by a caller that reaches every project; an API key or a member of selected projects hears 403 project_access_restricted.
Parameters
| Parameter | Description |
|---|---|
id requiredpath | Snowflake identifier, as a string.
|
Responses
The enabled connection
{
"data": {
"provider_connection_id": "74438200973594624",
"organization_id": "74438200973594624",
"project_id": "74438200973594624",
"provider": "openai",
"name": "string",
"environment": "production",
"region": "string",
"provider_organization_id": "74438200973594624",
"provider_project_id": "74438200973594624",
"status": "active",
"health_status": "healthy",
"cooldown_until": "2026-10-02T09:30:00Z",
"error_rate": "string",
"secret_last_four": "string",
"secret_configured": true,
"last_health_check_at": "2026-10-02T09:30:00Z",
"last_health_latency_ms": 1,
"deleted_at": "2026-10-02T09:30:00Z",
"created_at": "2026-10-02T09:30:00Z",
"updated_at": "2026-10-02T09:30:00Z"
}
}Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. |
Headers
X-Request-Id
The body of every error is the error envelope.
Stop using this connection without deleting it
POST /v1/provider-connections/{id}/disable
- Scope:
management:write
A connection of no project (the organization's) is written only by a caller that reaches every project; an API key or a member of selected projects hears 403 project_access_restricted.
Parameters
| Parameter | Description |
|---|---|
id requiredpath | Snowflake identifier, as a string.
|
Responses
The disabled connection
{
"data": {
"provider_connection_id": "74438200973594624",
"organization_id": "74438200973594624",
"project_id": "74438200973594624",
"provider": "openai",
"name": "string",
"environment": "production",
"region": "string",
"provider_organization_id": "74438200973594624",
"provider_project_id": "74438200973594624",
"status": "active",
"health_status": "healthy",
"cooldown_until": "2026-10-02T09:30:00Z",
"error_rate": "string",
"secret_last_four": "string",
"secret_configured": true,
"last_health_check_at": "2026-10-02T09:30:00Z",
"last_health_latency_ms": 1,
"deleted_at": "2026-10-02T09:30:00Z",
"created_at": "2026-10-02T09:30:00Z",
"updated_at": "2026-10-02T09:30:00Z"
}
}Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. |
Headers
X-Request-Id
The body of every error is the error envelope.
Reach out to the provider and report what came back
POST /v1/provider-connections/{id}/test
- Scope:
management:write
Tighter bucket than the rest of the plane (6/min per key): this call leaves our network.
The verdict is stored. A refused key marks an active connection invalid_credentials (it leaves pool selection); a later good answer, or a new key (PATCH with api_key), lifts it back to active. A disabled or deleted connection keeps its status whatever the answer. A disabled connection is switched back on only by an explicit action — POST /v1/provider-connections/{id}/enable or status in PATCH; a deleted one only by enable, which clears its deletion.
A connection of no project (the organization's) is written only by a caller that reaches every project; an API key or a member of selected projects hears 403 project_access_restricted.
Parameters
| Parameter | Description |
|---|---|
id requiredpath | Snowflake identifier, as a string.
|
Responses
The verification result
{
"data": {
"ok": true,
"latency_ms": 1,
"checked_at": "2026-10-02T09:30:00Z",
"error_code": "string",
"rate_limited": true
}
}Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. | |
| 429 | Rate limited for this API key |
Headers
X-Request-IdRetry-After429
The body of every error is the error envelope.
Rate limits configured for a connection
GET /v1/provider-connections/{id}/limits
- Scope:
management:read
Parameters
| Parameter | Description |
|---|---|
id requiredpath | Snowflake identifier, as a string.
|
Responses
One row per model, plus the connection-wide default
{
"data": [
{
"model": "gpt-4o-mini",
"rpm": 1,
"tpm": 1,
"input_tpm": 1,
"output_tpm": 1,
"max_concurrency": 1,
"daily_quota": 1,
"source": "manual"
}
]
}Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. |
Headers
X-Request-Id
The body of every error is the error envelope.
Write the rate limits of a connection, one model at a time
PUT /v1/provider-connections/{id}/limits
- Scope:
management:write
Writes the rows it names and leaves the others as they are: each item of limits is the row of one model (empty or null — the connection-wide row), and that row's six values are replaced as a whole — a value left out is no longer limited. An item whose six values are all empty removes its row. A row the body does not name keeps what it had, so this is not a replacement of the connection's limits: to drop a row, name it with no values. A written row becomes source: manual. Items are applied in order, so a model named twice ends with its last item. The answer is every row the connection has after the write.
A connection of no project (the organization's) is written only by a caller that reaches every project; an API key or a member of selected projects hears 403 project_access_restricted.
Parameters
| Parameter | Description |
|---|---|
id requiredpath | Snowflake identifier, as a string.
|
Request body
{
"limits": [
{
"model": "gpt-4o-mini",
"rpm": 1,
"tpm": 1,
"input_tpm": 1,
"output_tpm": 1,
"max_concurrency": 1,
"daily_quota": 1
}
]
}Responses
The stored limits
{
"data": [
{
"model": "gpt-4o-mini",
"rpm": 1,
"tpm": 1,
"input_tpm": 1,
"output_tpm": 1,
"max_concurrency": 1,
"daily_quota": 1,
"source": "manual"
}
]
}Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. | |
| 422 | Validation failure or a semantically impossible request. Field-level validation from the framework answers |
Headers
X-Request-Id
The body of every error is the error envelope.
Park a connection for a while
POST /v1/provider-connections/{id}/cooldown
- Scope:
management:write
A connection of no project (the organization's) is written only by a caller that reaches every project; an API key or a member of selected projects hears 403 project_access_restricted.
Parameters
| Parameter | Description |
|---|---|
id requiredpath | Snowflake identifier, as a string.
|
Request body
{
"duration_seconds": 1,
"reason": "rate_limit"
}Responses
The cooldown in force
{
"data": {
"connection_id": "74438200973594624",
"reason": "rate_limit",
"source": "headers",
"starts_at": "2026-10-02T09:30:00Z",
"expires_at": "2026-10-02T09:30:00Z",
"retry_after_seconds": 1
}
}Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. | |
| 422 | Validation failure or a semantically impossible request. Field-level validation from the framework answers |
Headers
X-Request-Id
The body of every error is the error envelope.
End a cooldown early
DELETE /v1/provider-connections/{id}/cooldown
- Scope:
management:write
A connection of no project (the organization's) is written only by a caller that reaches every project; an API key or a member of selected projects hears 403 project_access_restricted.
Parameters
| Parameter | Description |
|---|---|
id requiredpath | Snowflake identifier, as a string.
|
Responses
Released
No body
Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. |
Headers
X-Request-Id
The body of every error is the error envelope.
Throughput, failures and latency of one connection
GET /v1/provider-connections/{id}/analytics
- Scope:
read
Parameters
| Parameter | Description |
|---|---|
id requiredpath | Snowflake identifier, as a string.
|
from optionalquery | Start of the window an analytics answer covers — a date the server can parse, ISO-8601 recommended (a value without an offset is read as UTC). Unlike the lists, each end is optional on its own and the window is never refused, only fitted (
|
to optionalquery | End of the window an analytics answer covers; now when absent. See
|
Responses
Connection analytics for the window
{
"data": {
"connection_id": "74438200973594624",
"window": {
"from": "2026-10-02T09:30:00Z",
"to": "2026-10-02T09:30:00Z"
},
"requests": 1,
"succeeded": 1,
"success_rate": "string",
"rate_limited_count": 1,
"timeout_count": 1,
"provider_error_count": 1,
"uncertain_count": 1,
"avg_latency_ms": 1,
"p95_latency_ms": 1,
"cost": "0.02700000",
"successful_failovers": 1,
"cooldown_seconds": 1
}
}Errors
| Status | Codes | When |
|---|---|---|
| 401 | No credential, or one that is not valid | |
| 403 | Authenticated, but not allowed: scope ( | |
| 404 | No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable. | |
| 422 | Validation failure or a semantically impossible request. Field-level validation from the framework answers |
Headers
X-Request-Id
The body of every error is the error envelope.
Examples
List connections
The two filters narrow the list to the active connections of one provider.
curl "https://api.slen.ai/api/v1/provider-connections?provider=openai&status=active" \
-H "Authorization: Bearer $SLEN_API_KEY"Store a provider key
scope puts the connection into the project of the key. The answer shows the last four characters of the provider's key and nothing more of it.
curl https://api.slen.ai/api/v1/provider-connections \
-H "Authorization: Bearer $SLEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"scope": "project",
"provider": "openai",
"name": "OpenAI production",
"api_key": "sk-proj-4f9a...c81d"
}'{
"data": {
"provider_connection_id": "74438912450035712",
"organization_id": "74438200973594112",
"project_id": "74438200973594624",
"provider": "openai",
"name": "OpenAI production",
"environment": "production",
"region": null,
"provider_organization_id": null,
"provider_project_id": null,
"status": "active",
"health_status": "healthy",
"cooldown_until": null,
"error_rate": null,
"secret_last_four": "c81d",
"secret_configured": true,
"last_health_check_at": null,
"last_health_latency_ms": null,
"deleted_at": null,
"created_at": "2026-10-02T08:12:30+00:00",
"updated_at": "2026-10-02T08:12:30+00:00"
}
}Read a connection
The answer is the connection, in the shape the answer above has.
curl https://api.slen.ai/api/v1/provider-connections/74438912450035712 \
-H "Authorization: Bearer $SLEN_API_KEY"Replace the key
The new key replaces the stored one. A connection in invalid_credentials becomes active again.
curl -X PATCH https://api.slen.ai/api/v1/provider-connections/74438912450035712 \
-H "Authorization: Bearer $SLEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"api_key": "sk-proj-77b2...e0a4"
}'Delete a connection
The answer has no body.
curl -X DELETE https://api.slen.ai/api/v1/provider-connections/74438912450035712 \
-H "Authorization: Bearer $SLEN_API_KEY"204 No Content
Enable a connection
The request has no body. The answer is the connection with status set to active.
curl -X POST https://api.slen.ai/api/v1/provider-connections/74438912450035712/enable \
-H "Authorization: Bearer $SLEN_API_KEY"Disable a connection
The answer is the connection with status and health_status set to disabled.
curl -X POST https://api.slen.ai/api/v1/provider-connections/74438912450035712/disable \
-H "Authorization: Bearer $SLEN_API_KEY"Test a connection
The provider accepted the key and answered in 184 milliseconds.
curl -X POST https://api.slen.ai/api/v1/provider-connections/74438912450035712/test \
-H "Authorization: Bearer $SLEN_API_KEY"{
"data": {
"ok": true,
"latency_ms": 184,
"checked_at": "2026-10-02T08:13:05+00:00",
"error_code": null,
"rate_limited": false
}
}Read the limits
The answer is the list of rows, in the shape the next example shows.
curl https://api.slen.ai/api/v1/provider-connections/74438912450035712/limits \
-H "Authorization: Bearer $SLEN_API_KEY"Set the limits
The first row has no model: it is the default of the connection. The second row limits one model.
curl -X PUT https://api.slen.ai/api/v1/provider-connections/74438912450035712/limits \
-H "Authorization: Bearer $SLEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"limits": [
{
"rpm": 500,
"tpm": 200000,
"max_concurrency": 20
},
{
"model": "gpt-4o-mini",
"rpm": 300
}
]
}'{
"data": [
{
"model": null,
"rpm": 500,
"tpm": 200000,
"input_tpm": null,
"output_tpm": null,
"max_concurrency": 20,
"daily_quota": null,
"source": "manual"
},
{
"model": "gpt-4o-mini",
"rpm": 300,
"tpm": null,
"input_tpm": null,
"output_tpm": null,
"max_concurrency": null,
"daily_quota": null,
"source": "manual"
}
]
}Start a cooldown
The connection is out of use for ten minutes. Without reason the cooldown is manual.
curl https://api.slen.ai/api/v1/provider-connections/74438912450035712/cooldown \
-H "Authorization: Bearer $SLEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"duration_seconds": 600
}'{
"data": {
"connection_id": "74438912450035712",
"reason": "manual",
"source": "manual",
"starts_at": "2026-10-02T09:00:00+00:00",
"expires_at": "2026-10-02T09:10:00+00:00",
"retry_after_seconds": 600
}
}End a cooldown
The answer has no body.
curl -X DELETE https://api.slen.ai/api/v1/provider-connections/74438912450035712/cooldown \
-H "Authorization: Bearer $SLEN_API_KEY"204 No Content
Read how a connection behaved
The window follows the rules of a report: seven days without from and to, and at most 31 days.
curl "https://api.slen.ai/api/v1/provider-connections/74438912450035712/analytics?from=2026-09-25T00%3A00%3A00Z&to=2026-10-02T00%3A00%3A00Z" \
-H "Authorization: Bearer $SLEN_API_KEY"Where to go next
Connections — the same connections in the console.
Authentication — what a key reaches in its project and in its organization.
Analytics — how a report reads its window.
Models — the catalogue, with the provider of each model.
Error codes — every code of the API, what it means and what to do about it.
Provider pools — group the connections and arrange them for failover.
Built from openapi b070e1f, sdk contract 5cc7055, php ae4a53b, node 84bc62d