Authentication
The Curate-Me API uses JWT (JSON Web Tokens) for authentication. Access tokens are short-lived and refresh tokens allow you to obtain new access tokens without re-authenticating.
Token Lifetimes
| Token | Lifetime | Purpose |
|---|---|---|
| Access token | 30 minutes | Authorize API requests |
| Refresh token | 7 days | Obtain new access tokens |
Register
Create a new user account.
POST /api/v1/auth/registerRequest:
{
"email": "user@example.com",
"password": "securePassword123",
"name": "Jane Doe"
}Response (201):
{
"user": {
"id": "usr_abc123",
"email": "user@example.com",
"name": "Jane Doe",
"created_at": "2026-01-15T10:30:00Z"
},
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"expires_in": 1800
}Login
Authenticate with email and password.
POST /api/v1/auth/loginRequest:
{
"email": "user@example.com",
"password": "securePassword123"
}Response (200):
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"expires_in": 1800
}Refresh Token
Exchange a valid refresh token for a new access token.
POST /api/v1/auth/refreshRequest:
{
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}Response (200):
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"expires_in": 1800
}Logout
Invalidate the current access and refresh tokens.
POST /api/v1/auth/logoutHeaders:
Authorization: Bearer {access_token}Request:
{
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}Response (204): No content.
Using Tokens
Include the access token in the Authorization header on all authenticated requests:
curl -X GET https://api.curate-me.ai/api/v1/user/profile \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."B2B Organization Context
For B2B API requests, include the X-Org-ID header to specify the organization context. The middleware resolves organization identity in the following priority order:
- JWT claims —
org_idandorg_roleembedded in the token payload. - X-Org-ID header — Passed explicitly by the dashboard client.
- URL path parameter — Extracted from
/organizations/{org_id}/...routes.
curl -X GET https://api-admin.curate-me.ai/api/v1/admin/agents/status \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "X-Org-ID: org_xyz789"B2B API Keys
For server-to-server integrations, you can create long-lived API keys instead of using JWT tokens.
Create an API Key
POST /api/v1/b2b/api-keysHeaders:
Authorization: Bearer {access_token}
X-Org-ID: org_xyz789Request:
{
"name": "Production Integration",
"scopes": ["agents:read", "workflows:read", "workflows:execute", "costs:read"]
}Response (201):
{
"id": "key_abc123",
"name": "Production Integration",
"key": "cm_live_sk_abc123def456...",
"scopes": ["agents:read", "workflows:read", "workflows:execute", "costs:read"],
"created_at": "2026-01-15T10:30:00Z"
}The full key value is only returned once at creation time. Store it securely.
Using API Keys
Pass the API key in the X-API-Key header:
curl -X GET https://api-admin.curate-me.ai/api/v1/admin/agents/status \
-H "X-API-Key: cm_live_sk_abc123def456..."API keys are scoped to a specific organization and do not require the X-Org-ID header.