Create an integration

View as Markdown
Registers an integration with credentials you supply, then immediately runs a connection test. The response reflects the test: - `status: active` — the test passed (today, always the case for `webhook`). - `status: error` with `last_error` — the test threw. Every provider other than `webhook` lands here, because their adapters moved to the connected-apps catalogue; `last_error` says so. - `status: pending_auth` — the test returned "not connected" without an error. The integration is stored in every case. For OAuth2 providers use `GET /api/integrations/oauth/authorize` instead, which creates the integration when consent completes. A `webhook` integration receives pushes at `/webhooks/integrations/v2/{inbound_webhook_uuid}` with the `x-webhook-secret` header; no endpoint in this API sets `webhook_secret`, and pushes are answered `401` until one is set. **Side effects.** Encrypts and stores the credentials; runs the provider test; posts an in-app notification (connected or failed); writes an audit entry (action `create`, resource `integration`, credentials redacted). **Idempotency.** Not idempotent, but a retry cannot create a duplicate: a second create for the same provider returns `409` while the first integration exists. **Webhook events.** `audit.log_recorded` for webhooks subscribed to it. See [Webhooks](/webhooks). **Access** - **Required scope:** `full`. Humans need the `admin` or `owner` role. - **Rate limit:** General API (120–600 requests/min per workspace by plan) plus the configuration-mutation limiter — 10 requests/min per workspace, shared with agent and other configuration writes. See [Rate limits](/rate-limits). - **Plan:** Counts against the integration cap. Every paid plan allows effectively unlimited integrations; a workspace with no active plan is refused.

Authentication

AuthorizationBearer
Workspace API key: `jl_` followed by 64 lowercase hex characters, created by the workspace owner in the dashboard (**Settings → API Keys**) and sent as `Authorization: Bearer jl_...`. The plaintext is shown once, at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys. | Scope | GET / HEAD | POST / PUT / PATCH / DELETE | Admin-only routes | | --- | --- | --- | --- | | `read` | Yes | No | No | | `write` | Yes | Yes | No | | `full` | Yes | Yes | Yes | Operations restricted to admins or owners reject keys without the `full` scope with `403`, and say so in their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret — that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds. See [Authentication](/authentication).

Request

This endpoint expects an object.
providerenumRequired

Provider to register. Only webhook has a built-in adapter; any other value is stored but its connection test fails (see the description). Unknown values are rejected with 400.

credentialsmap from strings to anyRequired

Provider-specific credentials as a JSON object (use {} for webhook). Encrypted at rest and never returned; responses show ***.

labelstringOptional<=200 characters
Display name shown in the dashboard.
fieldMappingmap from strings to stringsOptional

Source field name → Jelliu contact field (phoneNumber, email, whatsappNumber, name). Applied to inbound webhook payloads. For salesforce, keys must be valid Salesforce field identifiers or the request is rejected with 400.

campaignIdstringOptionalformat: "uuid"

Campaign that inbound contacts are added to. Required in practice for webhook integrations that receive contacts or leads.

Response

Integration stored. Check status and last_error for the connection test result.

dataobject

The full integration record returned by retrieve, create and update: every Integration field plus the columns below. credentials is still masked; OAuth tokens appear only as encrypted ciphertext.

Errors

400
Bad Request Error
401
Unauthorized Error
403
Forbidden Error
409
Conflict Error
429
Too Many Requests Error