API reference
Auth and API keys
Email login, token refresh, API keys, and session check.
On this page
Log in with email and password
POST/api/v1/auth/login-email
No auth
Authenticate a user using email and password.
Request body
application/x-www-form-urlencoded
| Field | Type | Description |
|---|---|---|
client_id | string | null | |
client_secret | string (password) | null | |
grant_type | string | null | Limits: |
passwordrequired | string (password) | |
scope | string | Default: |
usernamerequired | string |
Example request
curl -X POST "https://api.cognichem.com/api/v1/auth/login-email" \
--data-urlencode '[email protected]' \
--data-urlencode 'password=YOUR_PASSWORD'from cognichem_client import CogniChem
client = CogniChem()
result = client.auth.login_email(
email="[email protected]",
password="YOUR_PASSWORD",
)
print(result)Python SDK pip install cognichem-client (1.1 or later).
Responses
Successful Response · application/json · TokenResponse
| Field | Type | Description |
|---|---|---|
access_tokenrequired | string | The access token for API authentication. |
expires_atrequired | integer | Expiration time of the access token as a UNIX timestamp. |
expires_inrequired | integer | Lifetime of the access token in seconds. |
refresh_tokenrequired | string | The refresh token for obtaining new access tokens. |
token_type | string | The type of token (typically "bearer"). Default: |
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_at": 1716123456,
"expires_in": 3600,
"refresh_token": "v1.MRj...",
"token_type": "bearer"
}Errors are RFC 7807 problem details (application/problem+json) with status, title, detail, request_id, and a retryability hint (validation, auth, quota, conflict, upstream, timeout, or terminal). Handling errors
| Status | When |
|---|---|
400 | Invalid input or business rule violation. |
401 | Missing or invalid credentials. |
402 | Wallet cannot cover the Assistant turn hold. |
403 | Authenticated but not allowed to access the resource. |
404 | Resource not found or not owned by the user. |
409 | Conflict (e.g. idempotency key reuse with a different body). |
413 | Request body or workflow spec exceeds size caps. |
422 | Request body or query failed validation. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
503 | Dependency temporarily unavailable. |
Check credentials
GET/api/v1/auth/check
API key or token
Check if the current user is authenticated.
Example request
curl "https://api.cognichem.com/api/v1/auth/check" \
-H "X-Api-Key: $COGNICHEM_API_KEY"from cognichem_client import CogniChem
client = CogniChem.from_env()
result = client.auth.check()
print(result)Python SDK pip install cognichem-client (1.1 or later). from_env() reads COGNICHEM_API_KEY.
Responses
Successful Response · application/json · MessageResponse
| Field | Type | Description |
|---|---|---|
messagerequired | string | The message content. |
Errors are RFC 7807 problem details (application/problem+json) with status, title, detail, request_id, and a retryability hint (validation, auth, quota, conflict, upstream, timeout, or terminal). Handling errors
| Status | When |
|---|---|
400 | Invalid input or business rule violation. |
401 | Missing or invalid credentials. |
402 | Wallet cannot cover the Assistant turn hold. |
403 | Authenticated but not allowed to access the resource. |
404 | Resource not found or not owned by the user. |
409 | Conflict (e.g. idempotency key reuse with a different body). |
413 | Request body or workflow spec exceeds size caps. |
422 | Request body or query failed validation. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
503 | Dependency temporarily unavailable. |
Refresh an access token (deprecated GET)
GET/api/v1/auth/refresh
No authDeprecated
Deprecated. Use POST /auth/refresh with a JSON body {"refresh_token": "…"}. This route puts the refresh token in the URL and stops working after Fri, 01 Jan 2027 00:00:00 GMT.
Parameters
| Name | Type | Description |
|---|---|---|
refresh_tokenrequired | string |
Example request
curl "https://api.cognichem.com/api/v1/auth/refresh?refresh_token=REFRESH_TOKEN"from cognichem_client import CogniChem
client = CogniChem()
result = client.auth.refresh("REFRESH_TOKEN")
print(result)Python SDK pip install cognichem-client (1.1 or later).
Responses
Successful Response · application/json · TokenResponse
| Field | Type | Description |
|---|---|---|
access_tokenrequired | string | The access token for API authentication. |
expires_atrequired | integer | Expiration time of the access token as a UNIX timestamp. |
expires_inrequired | integer | Lifetime of the access token in seconds. |
refresh_tokenrequired | string | The refresh token for obtaining new access tokens. |
token_type | string | The type of token (typically "bearer"). Default: |
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_at": 1716123456,
"expires_in": 3600,
"refresh_token": "v1.MRj...",
"token_type": "bearer"
}Errors are RFC 7807 problem details (application/problem+json) with status, title, detail, request_id, and a retryability hint (validation, auth, quota, conflict, upstream, timeout, or terminal). Handling errors
| Status | When |
|---|---|
400 | Invalid input or business rule violation. |
401 | Missing or invalid credentials. |
402 | Wallet cannot cover the Assistant turn hold. |
403 | Authenticated but not allowed to access the resource. |
404 | Resource not found or not owned by the user. |
409 | Conflict (e.g. idempotency key reuse with a different body). |
413 | Request body or workflow spec exceeds size caps. |
422 | Request body or query failed validation. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
503 | Dependency temporarily unavailable. |
Refresh an access token
POST/api/v1/auth/refresh
No auth
Refresh the user's access and refresh tokens.
Send the refresh token in the JSON body so it stays out of URLs and access logs.
Request body
application/json · RefreshTokenRequest
| Field | Type | Description |
|---|---|---|
refresh_tokenrequired | string | Refresh token from login or a previous refresh. Limits: |
Example request
curl -X POST "https://api.cognichem.com/api/v1/auth/refresh" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "v1.MRj..."
}'import httpx
response = httpx.post(
"https://api.cognichem.com/api/v1/auth/refresh",
json={"refresh_token": "v1.MRj..."},
)
response.raise_for_status()
print(response.json())Uses httpx; the Python SDK has no method for this endpoint.
Responses
Successful Response · application/json · TokenResponse
| Field | Type | Description |
|---|---|---|
access_tokenrequired | string | The access token for API authentication. |
expires_atrequired | integer | Expiration time of the access token as a UNIX timestamp. |
expires_inrequired | integer | Lifetime of the access token in seconds. |
refresh_tokenrequired | string | The refresh token for obtaining new access tokens. |
token_type | string | The type of token (typically "bearer"). Default: |
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_at": 1716123456,
"expires_in": 3600,
"refresh_token": "v1.MRj...",
"token_type": "bearer"
}Errors are RFC 7807 problem details (application/problem+json) with status, title, detail, request_id, and a retryability hint (validation, auth, quota, conflict, upstream, timeout, or terminal). Handling errors
| Status | When |
|---|---|
400 | Invalid input or business rule violation. |
401 | Missing or invalid credentials. |
402 | Wallet cannot cover the Assistant turn hold. |
403 | Authenticated but not allowed to access the resource. |
404 | Resource not found or not owned by the user. |
409 | Conflict (e.g. idempotency key reuse with a different body). |
413 | Request body or workflow spec exceeds size caps. |
422 | Request body or query failed validation. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
503 | Dependency temporarily unavailable. |
Log out
GET/api/v1/auth/logout
API key or token
Log out the current user by invalidating their access token.
Example request
curl "https://api.cognichem.com/api/v1/auth/logout" \
-H "X-Api-Key: $COGNICHEM_API_KEY"from cognichem_client import CogniChem
client = CogniChem.from_env()
result = client.auth.logout()
print(result)Python SDK pip install cognichem-client (1.1 or later). from_env() reads COGNICHEM_API_KEY.
Responses
Successful Response · application/json · MessageResponse
| Field | Type | Description |
|---|---|---|
messagerequired | string | The message content. |
Errors are RFC 7807 problem details (application/problem+json) with status, title, detail, request_id, and a retryability hint (validation, auth, quota, conflict, upstream, timeout, or terminal). Handling errors
| Status | When |
|---|---|
400 | Invalid input or business rule violation. |
401 | Missing or invalid credentials. |
402 | Wallet cannot cover the Assistant turn hold. |
403 | Authenticated but not allowed to access the resource. |
404 | Resource not found or not owned by the user. |
409 | Conflict (e.g. idempotency key reuse with a different body). |
413 | Request body or workflow spec exceeds size caps. |
422 | Request body or query failed validation. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
503 | Dependency temporarily unavailable. |
List API keys
GET/api/v1/auth/api-keys
Access token only
List API keys for the current user (metadata only; no secrets).
Example request
curl "https://api.cognichem.com/api/v1/auth/api-keys" \
-H "Authorization: Bearer $COGNICHEM_ACCESS_TOKEN"import os
from cognichem_client import CogniChem
client = CogniChem(access_token=os.environ["COGNICHEM_ACCESS_TOKEN"])
result = client.api_keys.list()
print(result)Python SDK pip install cognichem-client (1.1 or later).
Responses
Successful Response · application/json · ApiKeyListResponse
| Field | Type | Description |
|---|---|---|
countrequired | integer | Current number of keys. |
keys[]required | ApiKeyListItem[] | Owned keys, newest first (no secrets). |
keys.allow_structure_search | boolean | Owner opt-in for ChEMBL similarity / substructure via Default: |
keys.created_atrequired | string (date-time) | When the key was created. |
keys.expires_at | string (date-time) | null | When the key stops authenticating, if set. |
keys.idrequired | string | Credential row UUID. |
keys.key_prefix | string | null | Non-secret prefix for display and support. |
keys.last_used_at | string (date-time) | null | Last successful authentication time, if any. |
keys.namerequired | string | User-defined display name (unique per user). |
keys.revoked_at | string (date-time) | null | Soft-revoke timestamp when present. |
keys.rotated_at | string (date-time) | null | Last rotation time, if any. |
keys.scopes[] | string[] | Enforced v1 scopes ( |
keys.spend_accrued_usd | number | null | USD accrued in the current spend window. |
keys.spend_ceiling_usd | number | null | Optional per-key USD cap (null = wallet-only). |
limitrequired | integer | Maximum keys allowed for the user's subscription tier. |
{
"count": 1,
"keys": [
{
"created_at": "2026-05-21T12:00:00Z",
"id": "550e8400-e29b-41d4-a716-446655440000",
"key_prefix": "a1b2c3d4…",
"name": "Default",
"scopes": [
"read",
"write"
]
}
],
"limit": 50
}Errors are RFC 7807 problem details (application/problem+json) with status, title, detail, request_id, and a retryability hint (validation, auth, quota, conflict, upstream, timeout, or terminal). Handling errors
| Status | When |
|---|---|
400 | Invalid input or business rule violation. |
401 | Missing or invalid credentials. |
402 | Wallet cannot cover the Assistant turn hold. |
403 | Authenticated but not allowed to access the resource. |
404 | Resource not found or not owned by the user. |
409 | Conflict (e.g. idempotency key reuse with a different body). |
413 | Request body or workflow spec exceeds size caps. |
422 | Request body or query failed validation. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
503 | Dependency temporarily unavailable. |
Create an API key
POST/api/v1/auth/api-keys
Access token only
Create a named API key and return the secret once.
Request body
application/json · CreateApiKeyRequest
| Field | Type | Description |
|---|---|---|
allow_structure_search | boolean | Let this key send SMILES to ChEMBL for similarity / substructure search via /lookup/chembl. Off by default. Default: |
expires_at | string (date-time) | null | Optional expiry. After this instant the key is rejected. |
namerequired | string | Display name (unique per user, 1–64 printable characters). Limits: |
scopes[] | string[] | null | Optional scopes (subset of read, write). Default is both. |
spend_ceiling_usd | number | null | Optional per-key USD spend cap. Null = wallet-only. Limits: |
Example request
curl -X POST "https://api.cognichem.com/api/v1/auth/api-keys" \
-H "Authorization: Bearer $COGNICHEM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "CI deploy"
}'import os
from cognichem_client import CogniChem
client = CogniChem(access_token=os.environ["COGNICHEM_ACCESS_TOKEN"])
result = client.api_keys.create("CI deploy")
print(result)Python SDK pip install cognichem-client (1.1 or later).
Responses
Successful Response · application/json · ApiKeyCreatedResponse
| Field | Type | Description |
|---|---|---|
allow_structure_search | boolean | Default: |
api_keyrequired | string | |
created_atrequired | string (date-time) | |
expires_at | string (date-time) | null | |
idrequired | string | |
key_prefix | string | null | |
last_used_at | string (date-time) | null | |
namerequired | string | |
revoked_at | string (date-time) | null | |
rotated_at | string (date-time) | null | |
scopes[] | string[] | |
spend_accrued_usd | number | null | |
spend_ceiling_usd | number | null |
{
"api_key": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"created_at": "2026-05-21T12:00:00Z",
"id": "550e8400-e29b-41d4-a716-446655440000",
"key_prefix": "a1b2c3d4…",
"name": "CI deploy",
"scopes": [
"read",
"write"
]
}Errors are RFC 7807 problem details (application/problem+json) with status, title, detail, request_id, and a retryability hint (validation, auth, quota, conflict, upstream, timeout, or terminal). Handling errors
| Status | When |
|---|---|
400 | Invalid input or business rule violation. |
401 | Missing or invalid credentials. |
402 | Wallet cannot cover the Assistant turn hold. |
403 | Authenticated but not allowed to access the resource. |
404 | Resource not found or not owned by the user. |
409 | Conflict (e.g. idempotency key reuse with a different body). |
413 | Request body or workflow spec exceeds size caps. |
422 | Request body or query failed validation. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
503 | Dependency temporarily unavailable. |
Get an API key
GET/api/v1/auth/api-keys/{key_id}
Access token only
Retrieve metadata for one owned API key.
Parameters
| Name | Type | Description |
|---|---|---|
key_idrequired | string (uuid) |
Example request
curl "https://api.cognichem.com/api/v1/auth/api-keys/KEY_ID" \
-H "Authorization: Bearer $COGNICHEM_ACCESS_TOKEN"import os
from cognichem_client import CogniChem
client = CogniChem(access_token=os.environ["COGNICHEM_ACCESS_TOKEN"])
result = client.api_keys.get("KEY_ID")
print(result)Python SDK pip install cognichem-client (1.1 or later).
Responses
Successful Response · application/json · ApiKeyListItem
| Field | Type | Description |
|---|---|---|
allow_structure_search | boolean | Owner opt-in for ChEMBL similarity / substructure via Default: |
created_atrequired | string (date-time) | When the key was created. |
expires_at | string (date-time) | null | When the key stops authenticating, if set. |
idrequired | string | Credential row UUID. |
key_prefix | string | null | Non-secret prefix for display and support. |
last_used_at | string (date-time) | null | Last successful authentication time, if any. |
namerequired | string | User-defined display name (unique per user). |
revoked_at | string (date-time) | null | Soft-revoke timestamp when present. |
rotated_at | string (date-time) | null | Last rotation time, if any. |
scopes[] | string[] | Enforced v1 scopes ( |
spend_accrued_usd | number | null | USD accrued in the current spend window. |
spend_ceiling_usd | number | null | Optional per-key USD cap (null = wallet-only). |
{
"created_at": "2026-05-21T12:00:00Z",
"id": "550e8400-e29b-41d4-a716-446655440000",
"key_prefix": "a1b2c3d4…",
"last_used_at": "2026-05-21T14:30:00Z",
"name": "CI deploy",
"scopes": [
"read",
"write"
]
}Errors are RFC 7807 problem details (application/problem+json) with status, title, detail, request_id, and a retryability hint (validation, auth, quota, conflict, upstream, timeout, or terminal). Handling errors
| Status | When |
|---|---|
400 | Invalid input or business rule violation. |
401 | Missing or invalid credentials. |
402 | Wallet cannot cover the Assistant turn hold. |
403 | Authenticated but not allowed to access the resource. |
404 | Resource not found or not owned by the user. |
409 | Conflict (e.g. idempotency key reuse with a different body). |
413 | Request body or workflow spec exceeds size caps. |
422 | Request body or query failed validation. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
503 | Dependency temporarily unavailable. |
Rename an API key
PATCH/api/v1/auth/api-keys/{key_id}
Access token only
Rename an owned API key and/or set its structure-search opt-in.
Parameters
| Name | Type | Description |
|---|---|---|
key_idrequired | string (uuid) |
Request body
application/json · RenameApiKeyRequest
| Field | Type | Description |
|---|---|---|
allow_structure_search | boolean | null | Let this key send SMILES to ChEMBL for similarity / substructure search via /lookup/chembl. Only the owner's JWT can change it. |
name | string | null | New display name (unique per user). Limits: |
Example request
curl -X PATCH "https://api.cognichem.com/api/v1/auth/api-keys/KEY_ID" \
-H "Authorization: Bearer $COGNICHEM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"allow_structure_search": false,
"name": "Production"
}'import os
from cognichem_client import CogniChem
client = CogniChem(access_token=os.environ["COGNICHEM_ACCESS_TOKEN"])
result = client.api_keys.update(
"KEY_ID",
name="Production",
allow_structure_search=False,
)
print(result)Python SDK pip install cognichem-client (1.1 or later).
Responses
Successful Response · application/json · ApiKeyListItem
| Field | Type | Description |
|---|---|---|
allow_structure_search | boolean | Owner opt-in for ChEMBL similarity / substructure via Default: |
created_atrequired | string (date-time) | When the key was created. |
expires_at | string (date-time) | null | When the key stops authenticating, if set. |
idrequired | string | Credential row UUID. |
key_prefix | string | null | Non-secret prefix for display and support. |
last_used_at | string (date-time) | null | Last successful authentication time, if any. |
namerequired | string | User-defined display name (unique per user). |
revoked_at | string (date-time) | null | Soft-revoke timestamp when present. |
rotated_at | string (date-time) | null | Last rotation time, if any. |
scopes[] | string[] | Enforced v1 scopes ( |
spend_accrued_usd | number | null | USD accrued in the current spend window. |
spend_ceiling_usd | number | null | Optional per-key USD cap (null = wallet-only). |
{
"created_at": "2026-05-21T12:00:00Z",
"id": "550e8400-e29b-41d4-a716-446655440000",
"key_prefix": "a1b2c3d4…",
"last_used_at": "2026-05-21T14:30:00Z",
"name": "CI deploy",
"scopes": [
"read",
"write"
]
}Errors are RFC 7807 problem details (application/problem+json) with status, title, detail, request_id, and a retryability hint (validation, auth, quota, conflict, upstream, timeout, or terminal). Handling errors
| Status | When |
|---|---|
400 | Invalid input or business rule violation. |
401 | Missing or invalid credentials. |
402 | Wallet cannot cover the Assistant turn hold. |
403 | Authenticated but not allowed to access the resource. |
404 | Resource not found or not owned by the user. |
409 | Conflict (e.g. idempotency key reuse with a different body). |
413 | Request body or workflow spec exceeds size caps. |
422 | Request body or query failed validation. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
503 | Dependency temporarily unavailable. |
Revoke an API key
DELETE/api/v1/auth/api-keys/{key_id}
Access token only
Revoke (hard-delete) an owned API key.
Parameters
| Name | Type | Description |
|---|---|---|
key_idrequired | string (uuid) |
Example request
curl -X DELETE "https://api.cognichem.com/api/v1/auth/api-keys/KEY_ID" \
-H "Authorization: Bearer $COGNICHEM_ACCESS_TOKEN"import os
from cognichem_client import CogniChem
client = CogniChem(access_token=os.environ["COGNICHEM_ACCESS_TOKEN"])
result = client.api_keys.delete("KEY_ID")
print(result)Python SDK pip install cognichem-client (1.1 or later).
Responses
Successful Response
Errors are RFC 7807 problem details (application/problem+json) with status, title, detail, request_id, and a retryability hint (validation, auth, quota, conflict, upstream, timeout, or terminal). Handling errors
| Status | When |
|---|---|
400 | Invalid input or business rule violation. |
401 | Missing or invalid credentials. |
402 | Wallet cannot cover the Assistant turn hold. |
403 | Authenticated but not allowed to access the resource. |
404 | Resource not found or not owned by the user. |
409 | Conflict (e.g. idempotency key reuse with a different body). |
413 | Request body or workflow spec exceeds size caps. |
422 | Request body or query failed validation. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
503 | Dependency temporarily unavailable. |
Rotate an API key
POST/api/v1/auth/api-keys/{key_id}/rotate
Access token only
Rotate an owned API key and return the new secret once.
Parameters
| Name | Type | Description |
|---|---|---|
key_idrequired | string (uuid) |
Example request
curl -X POST "https://api.cognichem.com/api/v1/auth/api-keys/KEY_ID/rotate" \
-H "Authorization: Bearer $COGNICHEM_ACCESS_TOKEN"import os
from cognichem_client import CogniChem
client = CogniChem(access_token=os.environ["COGNICHEM_ACCESS_TOKEN"])
result = client.api_keys.rotate("KEY_ID")
print(result)Python SDK pip install cognichem-client (1.1 or later).
Responses
Successful Response · application/json · ApiKeyCreatedResponse
| Field | Type | Description |
|---|---|---|
allow_structure_search | boolean | Default: |
api_keyrequired | string | |
created_atrequired | string (date-time) | |
expires_at | string (date-time) | null | |
idrequired | string | |
key_prefix | string | null | |
last_used_at | string (date-time) | null | |
namerequired | string | |
revoked_at | string (date-time) | null | |
rotated_at | string (date-time) | null | |
scopes[] | string[] | |
spend_accrued_usd | number | null | |
spend_ceiling_usd | number | null |
{
"api_key": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"created_at": "2026-05-21T12:00:00Z",
"id": "550e8400-e29b-41d4-a716-446655440000",
"key_prefix": "a1b2c3d4…",
"name": "CI deploy",
"scopes": [
"read",
"write"
]
}Errors are RFC 7807 problem details (application/problem+json) with status, title, detail, request_id, and a retryability hint (validation, auth, quota, conflict, upstream, timeout, or terminal). Handling errors
| Status | When |
|---|---|
400 | Invalid input or business rule violation. |
401 | Missing or invalid credentials. |
402 | Wallet cannot cover the Assistant turn hold. |
403 | Authenticated but not allowed to access the resource. |
404 | Resource not found or not owned by the user. |
409 | Conflict (e.g. idempotency key reuse with a different body). |
413 | Request body or workflow spec exceeds size caps. |
422 | Request body or query failed validation. |
429 | Rate limit exceeded. |
500 | Unexpected server error. |
503 | Dependency temporarily unavailable. |