Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.open.cx/llms.txt

Use this file to discover all available pages before exploring further.

Authentication

All Partner API requests require a Bearer token in the Authorization header. Partner API keys are provisioned by the OpenCX team — they are separate from org-level API keys.
Authorization: Bearer YOUR_PARTNER_API_KEY
Base URL: https://api.open.cx

IP allow list

Partner API endpoints support IP-level access control. When an allow list is configured on your partner account, requests from IPs not in the list are rejected with 403 Forbidden — even with a valid API key. All traffic passes through Cloudflare, which forwards the real client IP in the X-Forwarded-For header. The backend extracts and validates this IP on every request.
IP allow lists are configured by the OpenCX team during onboarding. Contact us to add, update, or remove IPs. When no allow list is set, requests are accepted from any IP (token-only authentication).

Security layers

LayerWhat it does
Bearer tokenEvery request must include a valid partner API JWT. Revoked or missing keys return 401.
IP allow listWhen configured, only requests from whitelisted IPs are accepted. Others get 403.
Partner active checkInactive partner accounts are blocked at the auth layer (401).
Rate limiting100 req/min per partner globally, plus per-endpoint limits.
Org ownershipAll org-scoped endpoints verify the org belongs to the calling partner (403 otherwise).

Create Org

Create a new organization for one of your customers.
POST /partner/v1/orgs

Request body

FieldTypeRequiredDescription
namestringYesDisplay name for the org.
external_idstringNoYour internal ID for this customer. Must be unique per partner — duplicates return 409.
websitestringNoCustomer’s website URL.
languagestringNoDefault language code (e.g. "en", "es", "de"). Defaults to "en".
ai_instructionsstringNoThe AI profile — system prompt that defines the agent’s personality, knowledge scope, and behavior. Overrides your partner-level default if set.
integrationsobjectNoAuto-connect integrations during creation. See below.

Integrations

Pass credentials in the integrations object to auto-connect supported third-party integrations during org creation. Credentials are validated against the live third-party API — invalid credentials cause the request to fail with a 400. Each integration has its own shape under its own key. Some integrations accept either a single object (for one connection) or an array (for multiple connections — different locations, brands, or currencies). When passing an array, each entry should include a name that the AI uses in conversations to disambiguate between connections. Single connection (object form):
{
  "integrations": {
    "example_integration": {
      "name": "Primary",
      "app_key": "...",
      "user_key": "..."
    }
  }
}
Multiple connections (array form):
{
  "integrations": {
    "example_integration": [
      { "name": "Account A", "app_key": "...", "user_key": "..." },
      { "name": "Account B", "app_key": "...", "user_key": "..." }
    ]
  }
}
Supported integration keys and their per-integration field shapes are documented on each integration’s page. This section will expand as more integrations become available via the provisioning API. For integrations not yet supported here, use the org-level dashboard or API after creation.

Response

201 Created
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Acme Tours",
  "widget_token": "f8e7d6c5b4a39281...",
  "external_id": "customer-12345"
}
FieldTypeDescription
idstringThe org UUID. Use this to manage the org via other OpenCX APIs.
namestringThe org name as provided.
widget_tokenstringWidget embed token. Pass this to the chat widget.
external_idstring | nullYour external ID, echoed back.

Error responses

StatusConditionBody
400Invalid request body, or integration credentials failed validation.{ "statusCode": 400, "message": "..." }
401Missing, invalid, or revoked API key.{ "statusCode": 401, "message": "..." }
409An org with this external_id already exists for your partner.{ "statusCode": 409, "message": "Org with external_id \"...\" already exists" }

Examples

curl -X POST https://api.open.cx/partner/v1/orgs \
  -H "Authorization: Bearer YOUR_PARTNER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Tours",
    "external_id": "customer-12345",
    "language": "en",
    "ai_instructions": "You are a support agent for Acme Tours. Help customers with bookings and questions."
  }'

List Orgs

List all organizations created by your partner account.
GET /partner/v1/orgs

Query parameters

ParameterTypeDefaultDescription
limitnumber50Number of orgs to return (1–100).
offsetnumber0Number of orgs to skip (for pagination).

Response

200 OK
{
  "data": [
    {
      "id": "a1b2c3d4-...",
      "name": "Acme Tours",
      "widget_token": "f8e7d6c5b4a3...",
      "external_id": "customer-12345",
      "created_at": "2026-03-15T10:30:00.000Z"
    }
  ],
  "total": 142
}

Examples

curl "https://api.open.cx/partner/v1/orgs?limit=10&offset=0" \
  -H "Authorization: Bearer YOUR_PARTNER_API_KEY"

Get Org by external_id

Look up a single org by the external_id you supplied at creation. Use this when you need to reverse-resolve from your internal identifier to the OpenCX org — for example, before creating an API key or generating a login link — without paginating through /orgs.
GET /partner/v1/orgs/by-external-id/:externalId

Path parameters

ParameterTypeDescription
externalIdstringThe external_id you set when calling POST /partner/v1/orgs. URL-encode it if it contains reserved characters.

Response

200 OK
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Acme Tours",
  "widget_token": "f8e7d6c5b4a39281...",
  "external_id": "customer-12345",
  "created_at": "2026-03-15T10:30:00.000Z"
}

Error responses

StatusCondition
401Invalid or revoked partner API key.
404No org with this external_id exists for your partner account.
Lookups are scoped to your partner account. If a different partner has an org with the same external_id, you will not see it — you only ever resolve orgs you created.

Examples

curl "https://api.open.cx/partner/v1/orgs/by-external-id/customer-12345" \
  -H "Authorization: Bearer YOUR_PARTNER_API_KEY"

Create Org API Key

Create an API key for a specific org. The returned key authenticates requests to the OpenCX Public API (crawling, training, contacts, etc).
POST /partner/v1/orgs/:orgId/api-keys

Request body

FieldTypeRequiredDescription
namestringNoA label for the key (e.g. "Production"). Defaults to "Default".

Response

201 Created
{
  "api_key_id": "key-uuid-here",
  "api_key": "eyJhbGciOi..."
}
FieldTypeDescription
api_key_idstringThe key’s UUID.
api_keystringThe JWT API key. Use this as Bearer token for org-level API calls.
The full API key is only returned once — store it securely. If lost, create a new one.

Examples

curl -X POST https://api.open.cx/partner/v1/orgs/ORG_ID/api-keys \
  -H "Authorization: Bearer YOUR_PARTNER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Production" }'

Error responses

StatusCondition
401Invalid or revoked partner API key.
403Org does not belong to this partner.

Generate a short-lived, single-use URL that logs a user directly into the dashboard with the correct org context. No email, no forms, no org picker — the user lands in the dashboard immediately. Use this instead of invitations when you want frictionless access — for example, embedding a “Manage support” button in your own platform that takes the user straight into their dashboard.
POST /partner/v1/orgs/:orgId/login-links

Request body

FieldTypeRequiredDescription
emailstringYesEmail address of the user. If no account exists, one is created automatically.
namestringNoDisplay name for the user (used only when creating a new account). Defaults to the email prefix.
role_idsstring[]NoArray of role UUIDs to assign when creating org membership. Ignored if user is already a member.

Response

201 Created
{
  "url": "https://platform.open.cx/partner-login?token=a1b2c3...",
  "expires_at": "2026-04-12T12:15:00.000Z"
}
FieldTypeDescription
urlstringThe login URL. Redirect the user’s browser here.
expires_atstringISO 8601 timestamp. The link expires 15 minutes after creation.
Login links are single-use — once a user visits the URL, it is consumed and cannot be reused. Generate a new link for each login session.

Security properties

PropertyValue
Token entropy256 bits (cryptographically random)
TTL15 minutes
Single-useToken deleted on first use
Rate limit30 links/min per partner

Error responses

StatusCondition
401Invalid or revoked partner API key.
403Org does not belong to this partner.

Examples

curl -X POST https://api.open.cx/partner/v1/orgs/ORG_ID/login-links \
  -H "Authorization: Bearer YOUR_PARTNER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "owner@acmetours.com", "name": "Jane Smith" }'

Idempotency

Use external_id to prevent duplicate orgs. If you call POST /partner/v1/orgs twice with the same external_id, the second call returns 409 Conflict. This makes it safe to retry org creation without risk of duplicates. Use GET /partner/v1/orgs/by-external-id/:externalId to resolve the existing org directly — no pagination required.
The external_id uniqueness constraint is scoped to your partner account. Different partners can use the same external_id values.