Skip to main content

Integrations API

Connect third-party SaaS apps (Salesforce, HubSpot, Shopify, Pipedrive, Zendesk, Intercom, …) and pull their data into Orbit for use in flows, AI agents, and contact enrichment. Auth, token refresh, rate limiting, and provider-specific quirks are handled for you. Base path: /api/v1/integrations Authentication: API key (X-API-Key) or session JWT. Connect, disconnect, and sync are owner/admin-only writes; list, status, and data reads require the integrations:read scope, writes the integrations:write scope. Every response below is wrapped in the standard envelope: a data payload plus a meta block with request_id and timestamp. Errors use an error object with code, message, and status.

Using the SDKs

This page’s endpoints sit outside the SDKs’ core typed resources, so every language below reaches them through the same generic escape hatch, which keeps auth, retries, and the response envelope identical to the typed resources. The Node SDK additionally ships a typed orbit.integrations surface for the catalog (listCatalog(), list(), sync()); the connect, status, disconnect, and data operations shown here ride the escape hatch in every language, and the per-operation samples further down the page run the same calls as the curl examples.
  • Node.js (@devotel-orbit/node) — orbit.request<T>(method, path, body?)
  • Python (orbit_sdk) — client.request(method, path, params={...}, json_body={...})
  • Go (orbit-go) — client.Request(ctx, method, path, query, body, out, idempotencyKey)
  • Ruby (orbit_sdk) — client.request(method, path, query: {...}, json_body: {...})
  • PHP (Devotel\Orbit) — $client->request(method: ..., path: ..., query: [...], jsonBody: [...])
The Python SDK is core-scope — it wraps the 8 core resources (messaging, voice, contacts, campaigns, verify, numbers) and reaches everything else through the same escape hatch. See the Python SDK. Returns the typed ApiResponse envelope. See the SDK index at SDK quickstart.

Connections

Sync & data

The sections below walk one end-to-end HubSpot connection: list the catalog, start the OAuth flow, confirm the connection, trigger a sync, read records, and disconnect.

WooCommerce (key-pair connect)

WooCommerce self-hosted does not run OAuth — it’s the one catalog entry that connects with a pasted REST API key pair instead of the consent flow. See Connect WooCommerce and Disconnect WooCommerce below.

Inbound webhook

The integration server posts auth + sync events to POST /api/v1/integrations/webhooks/nango — internal only. You don’t call this directly.

List integrations

GET /api/v1/integrations Returns every integration available to your organization with a connected flag, its provider, category, and the syncs it offers, cursor-paginated (?limit= + ?cursor=). Add a ?fields= projection (comma-separated field names) when you only need a couple of fields per item. If the integration server is unreachable, the route serves the built-in catalog with connected: false instead of an error, so your settings page always renders.

Start the OAuth connect flow

POST /api/v1/integrations/connect Initiates the OAuth authorization flow for one integration_id and returns the auth_url you redirect the operator to. Owner/admin only. A provider with no OAuth credentials set up yet returns 404; an integration-server outage returns 503. The narrative below uses HubSpot; swap the integration_id for any provider in the catalog.
Redirect the operator to auth_url. After they consent on the provider’s page, they’re returned to Orbit and the connection is established — from here on, syncs can run.

Check connection status

GET /api/v1/integrations/{id}/status Returns whether the integration is connected for your organization plus the connection metadata and the per-sync status when connected. A never-connected or revoked integration resolves to connected: false with an empty sync list — not a 4xx — so you can render a disconnected state without special-casing errors.
Disconnected — whether it was never connected or the tokens were revoked — looks like this:
200

Trigger a sync

POST /api/v1/integrations/{id}/sync Runs one sync immediately instead of waiting for its scheduled cadence. The body names the sync — for HubSpot that’s contacts, deals, or companies from the catalog entry. Owner/admin only. A failed upstream trigger returns 502; there is no job handle to poll — watch the last_sync_at timestamps on the status endpoint to see the run complete.

Read synced records

GET /api/v1/integrations/{id}/data?model={name} Returns the records the integration has synced for one model. model is a required query parameter and names the model in the sync’s vocabulary (contacts, deals, companies for HubSpot). The response is the full record set — the route walks the integration server’s record cursor for you, so there is no pagination to manage on this endpoint. An unconfigured integration server returns an empty array; a failed upstream fetch returns 502.
Record fields are the provider’s own, passed through unchanged — the envelope is normalized, the record body is not. Map the provider fields you need; anything absent from a record stays absent.

Connect WooCommerce (key-pair connect)

POST /api/v1/integrations/woocommerce/connect WooCommerce self-hosted stores don’t run OAuth, so the catalog’s OAuth flow doesn’t apply. Generate a REST API key pair in WP-Admin → WooCommerce → Settings → Advanced → REST API, then POST the store URL and both halves here. Owner/admin only. Idempotency-Key is honored, so a retry after a timeout is safe. Before storing anything, Orbit validates the pair live against the store with GET {store_url}/wp-json/wc/v3/orders?per_page=1: a 2xx stores the credentials, a 401/403 comes back as WOO_AUTH_FAILED, a failed or timed-out reach as WOO_UNREACHABLE. The store URL must be HTTPS and publicly reachable — private, loopback, and metadata endpoints are rejected. On success both halves are encrypted before they are written, and the integration card flips to Connected. Re-running connect with a new pair replaces the stored one — use it to rotate keys.
A rejected store URL looks like this — the failure_code field names the category so you can branch on it without string-matching the message:
422
failure_code is one of parse_error, protocol, blocked_host, internal_suffix, dns_invalid, or private_ip. Once connected, customers, orders, and products sync on the scheduled cadence, and order events land as woocommerce.order events flows can trigger on.

Disconnect WooCommerce

DELETE /api/v1/integrations/woocommerce/disconnect Drops the stored key pair for your organization. The store itself is untouched — revoke the key pair in WP-Admin too if you want it fully retired. Owner/admin only. Disconnecting an org that never connected returns 200, so the call is idempotent.

Disconnect

DELETE /api/v1/integrations/{id}/disconnect Revokes the OAuth connection. Provider tokens stop working immediately and no further syncs run. Owner/admin only. A failed upstream revoke returns 502 — retry rather than assuming it went through.
After the revoke, GET /{id}/status reports connected: false, and you can leave the revoked integration in your catalog or remove it from view entirely.

Same flow in Node fetch

No SDK required — plain Node 18+ fetch, dependency-free, walking the whole HubSpot narrative above.
More task-shaped recipes in the same curl + Node style: REST API recipes.

Errors

WooCommerce connect adds a few more: 400 WOO_INVALID_URL / WOO_HTTPS_REQUIRED for a malformed or non-HTTPS store_url, and 401 WOO_AUTH_FAILED when the store rejects the key pair — fix the pair in WP-Admin and retry. A disconnected integration is not an error — status and data reads stay 200 with connected: false / [] — so reserve error handling for the table above.

See also