Imports API
The one-click migration importer pulls your existing configuration and audience out of another provider and maps it onto Orbit. It runs as a five-step wizard: connect a source account, preview what will be imported (a dry run), run the import as a background job, watch its progress live, and reconcile any conflicts. Every credential you supply is used only to read your source account — phone numbers, messaging profiles, templates, contacts, conversations, and audiences. Orbit never sends messages or places calls through your old provider as a result of an import: outbound traffic always exits through Orbit. The credential is encrypted the moment you submit it, handed forward as an opaqueenvelope string, and removed from the job record once the import finishes.
Base path: /api/v1/imports
Authentication: Clerk session (Authorization: Bearer <token>) or API key (X-API-Key). Every endpoint requires an authenticated tenant.
Supported sources
The{source} path segment on the dry-run and run endpoints is one of:
Entity kinds
Each import selects a subset of entity kinds to pull. Every source advertises the kinds it supports; ask for between 1 and 10 per import.phone_numbers, messaging_services, templates, contacts, conversations, channels, flows, inboxes, tags, teammates, lists, segments
Step 1 — connect a source
The connect step exchanges your source credentials for an opaque, encryptedenvelope string. You pass that envelope to the dry-run and run steps; it is never stored in the browser and the raw secret is never echoed back.
Start the Twilio Connect authorization
GET /api/v1/imports/twilio/connectstate value to match against on the callback.
cURL
503 TWILIO_CONNECT_NOT_CONFIGURED when Twilio Connect is not enabled on the environment — fall back to Submit Twilio credentials manually below.
Complete the Twilio Connect authorization
GET /api/v1/imports/twilio/callbackstate, exchanges the authorization code for credentials, encrypts them, and issues a 302 redirect back into the import wizard with the envelope attached to the URL. You do not call this endpoint yourself — Twilio invokes it, and the raw access token is never returned to the browser.
Returns 400 when the authorization was denied or the code/state is missing or invalid.
Submit Twilio credentials manually
POST /api/v1/imports/twilio/manual-credentialsenvelope directly.
string
required
Twilio Account SID — starts with
AC followed by 32 hex characters.string
required
Twilio Auth Token, 8–256 characters.
cURL
Submit Telnyx / Klaviyo / MessageBird credentials manually
POST /api/v1/imports/telnyx/manual-credentialsPOST /api/v1/imports/klaviyo/manual-credentialsPOST /api/v1/imports/messagebird/manual-credentialsenvelope shape.
string
required
The provider API key. Telnyx V2 keys start with
KEY; Klaviyo private keys start with pk_; MessageBird access keys are alphanumeric (optionally prefixed live_ or test_).string
Optional display-only label shown in the wizard’s “Connected as” line. Up to 128 characters.
cURL
422 VALIDATION_ERROR when the key doesn’t match the provider’s format.
Step 2 — preview (dry run)
POST /api/v1/imports/{source}/dry-runstring
required
The encrypted credentials envelope from step 1.
array
required
1–10 entity kinds to preview (see Entity kinds).
integer
Twilio only — how many days of conversation history to include, 1–90. Twilio exposes at most 90 days of message history without an Insights subscription, so values above 90 are rejected.
cURL
Step 3 — run the import
POST /api/v1/imports/{source}/runjobId. Submit the same envelope and entities you previewed, optionally with a per-entity conflictPolicy.
string
required
The encrypted credentials envelope from step 1.
array
required
1–10 entity kinds to import.
integer
Twilio only — conversation lookback window, 1–90 days.
object
Optional map of entity kind → how to resolve a collision:
skip, overwrite, or merge. Kinds you omit fall back to skipping conflicting rows.cURL
jobId to watch it run.
Step 4 — track progress
Stream import job progress
GET /api/v1/imports/{jobId}/progresssnapshot of the current state, so a page that subscribes late renders immediately; keepalive comments arrive every 15 seconds and the stream closes automatically after one hour. A job that has already finished replays its final end frame and closes.
Frame events: snapshot, progress, status, end.
cURL
403 when the request origin isn’t allowed, or 404 when no such job exists for your tenant.
Get an import job
GET /api/v1/imports/{jobId}cURL
List recent import jobs
GET /api/v1/importscURL
Step 5 — cancel or roll back
Cancel a running import job
POST /api/v1/imports/{jobId}/cancelcancelled and the worker stops between pages on its next check. Only a job that is still pending or running can be cancelled.
cURL
404 NOT_FOUND when the job doesn’t exist, or 409 IMPORT_NOT_CANCELLABLE (with the current status in details.current_status) when the job has already reached a terminal state.
Roll back a completed import
POST /api/v1/imports/{jobId}/rollbackcURL
403 FORBIDDEN for a non-owner/admin caller, 404 NOT_FOUND when the job doesn’t exist, and 409 when the job is still running (IMPORT_STILL_RUNNING) or has already been rolled back (ALREADY_ROLLED_BACK).