The Platform Exports API lets you store platform credentials and export mailboxes to connected sequencing tools. Credentials are validated live against the external platform before anything is saved, so an invalid credential is rejected immediately — there's no way to store a broken credential and fix it later.Every stored credential gets a unique credentialId. Pass this ID on all subsequent calls — you never re-send raw credentials after the initial store.
| Platform | Identifier | Required fields | Notes |
|---|
| ReachInbox | REACHINBOX | credentials.email, credentials.password | Account must have an active paid plan — free/expired plans are rejected at validation |
| Smartlead | SMARTLEAD | credentials.email, credentials.password | Standard email + password, no extras |
| Instantly | INSTANTLY | credentials.email, credentials.password, orgId | orgId is required — use GET /platform-workspaces to discover the right ID |
| EmailBison | EMAILBISON | credentials.email, credentials.password, metadata.* | Requires a full metadata block — see EmailBison section below |
Endpoints#
| Method | Endpoint | Purpose |
|---|
POST | /exports/platform-credential | Validate & store credentials → returns credentialId |
GET | /exports/platform-credentials | List all stored credentials, grouped by platform |
GET | /exports/platform-workspaces | List available orgs for a stored INSTANTLY credential |
PUT | /exports/platform-credential | Rotate credentials or update org / metadata in place |
POST | /exports/platform-exports | Queue mailboxes for export (async) |
DELETE | /exports/platform-credential | Remove a stored credential |
ReachInbox#
ReachInbox only needs email + password. First you will need to pass these and create credentials. The one gotcha: free and expired accounts pass authentication but are explicitly rejected — your user must have an active paid plan.POST /exports/platform-credential
{
"app": "REACHINBOX",
"credentials": {
"email": "user@example.com",
"password": "secret"
}
}
Once you have a credentialId:POST /exports/platform-exports
{
"credentialId": "H8M9JV2S9HMPYFQW393AZHQVD4XM",
"mailboxIds": ["MB1...", "MB2..."]
}
Smartlead#
The simplest integration — just email + password, no platform-specific extras.POST /exports/platform-credential
{
"app": "SMARTLEAD",
"credentials": {
"email": "user@example.com",
"password": "secret"
}
}
POST /exports/platform-exports
{
"credentialId": "H8M9JV2S9HMPYFQW393AZHQVD4XM",
"mailboxIds": ["MB1...", "MB2..."]
}
Instantly#
Connecting an Instantly account is a three-step process: add the credentials, discover the available workspaces, then associate the credential with the workspace you want.Start by storing the Instantly email and password. This gives you a credentialId you can use for the next step.POST /exports/platform-credential
?userId=USR9ABCDEFGHIJKLMNOPQRSTUV12
{
"app": "INSTANTLY",
"credentials": {
"email": "user@example.com",
"password": "secret"
}
}
→ 200 { "credentialId": "H8M9JV2S9HMPYFQW393AZHQVD4XM" }
Step 2 — Get available workspacesUse the credentialId from Step 1 to fetch all Instantly workspaces the account has access to. Show this list to your user so they can pick the one they want to export into.GET /exports/platform-workspaces
?userId=USR9ABCDEFGHIJKLMNOPQRSTUV12&credentialId=H8M9JV2S9HMPYFQW393AZHQVD4XM
→ 200
{
"data": [
{ "orgId": "org_H8M9JV2S9HMP", "name": "Acme Corp" },
{ "orgId": "org_XYZ123456789", "name": "Acme Corp (Sales)" }
]
}
Step 3 — Associate the credential with the chosen workspaceUpdate the credential with the orgId the user selected. The same credentialId is now linked to that workspace.If this is not done, you will see the below errorThis INSTANTLY credential has no workspace associated. Use GET /exports/platform-workspaces to find your workspace and PUT /exports/platform-credential to set it before exporting.PUT /exports/platform-credential
?userId=USR9ABCDEFGHIJKLMNOPQRSTUV12&credentialId=H8M9JV2S9HMPYFQW393AZHQVD4XM
{ "orgId": "org_H8M9JV2S9HMP" }
→ 200
POST /exports/platform-exports
?userId=USR9ABCDEFGHIJKLMNOPQRSTUV12
{
"credentialId": "H8M9JV2S9HMPYFQW393AZHQVD4XM",
"mailboxIds": ["MB1...", "MB2..."]
}
→ 200 (queued)
Switching workspaces later on the same credential? Repeat Step 2 to get the new orgId, then repeat Step 3 to update — no need to re-add credentials.
EmailBison#
EmailBison requires a metadata block alongside credentials. All four metadata fields are mandatory — a missing or partial block is rejected with a descriptive error before anything is stored.| Field | Description |
|---|
appBaseUrl | Base URL of the EmailBison instance (e.g. https://app.emailbison.com) |
clientId | Client ID issued by EmailBison for your workspace |
appName | Display name (e.g. EmailBison) |
workspace | Workspace slug |
POST /exports/platform-credential
{
"app": "EMAILBISON",
"credentials": {
"email": "admin@emailbison.com",
"password": "secret"
},
"metadata": {
"appBaseUrl": "https://app.emailbison.com",
"clientId": "client_abc",
"appName": "EmailBison",
"workspace": "my-workspace"
}
}
→ 400 "Workspace not Found" ← workspace slug doesn't exist
→ 400 "Invalid Email Bison credentials" ← wrong email or password
→ 400 "Client ID mismatch" ← clientId doesn't match the account
→ 400 "Invalid Email Bison credentials - Please check App URL, Email, Password, Workspace and Client ID"
← generic fallback for connectivity issues
→ 200 { "credentialId": "H8M9JV2S9HMPYFQW393AZHQVD4XM" }
Updating metadata — use PUT to update any metadata fields. Supplied fields are merged with the existing metadata:PUT /exports/platform-credential?userId=USR9ABCDEFGHIJKLMNOPQRSTUV12&credentialId=H8M9JV2S9HMPYFQW393AZHQVD4XM
{
"metadata": {
"workspace": "new-workspace"
}
}
→ 200
ℹ️ clientId is not returned in GET /platform-credentials for security. All other metadata fields (appBaseUrl, appName, workspace) are included.
Returns one entry per supported platform, whether or not credentials are stored.{
"status": 200,
"message": "Connected accounts fetched successfully",
"data": {
"REACHINBOX": {
"connected": true,
"credentials": [
{
"credentialId": "H8M9JV2S9HMPYFQW393AZHQVD4XM",
"email": "user@example.com",
"connectedAt": "2026-08-01T10:00:00.000Z"
}
]
},
"SMARTLEAD": {
"connected": false,
"credentials": []
},
"INSTANTLY": {
"connected": true,
"credentials": [
{
"credentialId": "XYZ9ABCDEFGHIJKLMNOPQRSTUV12",
"email": "user@example.com",
"connectedAt": "2026-08-10T08:30:00.000Z"
}
]
},
"EMAILBISON": {
"connected": true,
"credentials": [
{
"credentialId": "AB12CDEFGHIJKLMNOPQRSTUVWX34",
"email": "admin@emailbison.com",
"connectedAt": "2026-08-12T12:00:00.000Z",
"metadata": {
"appBaseUrl": "https://app.emailbison.com",
"appName": "EmailBison",
"workspace": "my-workspace"
}
}
]
}
}
}
Tips#
💡 Save credentialId on your side — Store it against the user after POST /platform-credential. Don't call GET /platform-credentials just to look it up on every export.💡 Use PUT to rotate, not DELETE + POST — Updating a password or switching an org with PUT preserves the existing credentialId. Deleting and re-adding issues a new ID, breaking any reference you've stored.💡 Batch your mailboxes — Pass all mailboxIds in a single POST /platform-exports call. Each call creates one export batch; splitting them creates separate batches with no benefit.💡 INSTANTLY org discovery — call GET /platform-workspaces after storing the credential and let them select from the list and update the credential.💡 ReachInbox plan check — Tell your users upfront that free ReachInbox accounts will be rejected. The error "Your account does not have an active plan" will surface
Next Steps#
OAuth Exports
Export mailboxes via OAuth instead of stored credentials.
Mailboxes
Find the mailbox IDs you'll pass to platform-exports.
Mailbox Events
Track mailbox creation before exporting. Modified at 2026-08-20 09:59:23