API Reference

Account authorization

Import authentication session

Import a session URL or channel-specific credentials to begin authorization. TikTok session accounts use tiktok.cookies; pending requires checking authorization and runtime status until authorized and running. HTTP 200 does not by itself mean authorization is complete.

POSThttps://api.unifyport.ai/v1/accounts/{account_id}/auth/session

Supported channels

TelegramXFacebookTikTokWhatsApp Protocol

Before you call

Use a server-side X-Api-Key for the workspace that owns the resource. Replace every placeholder before running a sample.

Prepare the session material required by the channel: Telegram and X use an existing session URL or reference; only WhatsApp Protocol uses the whatsapp-protocol credential object. Follow the channel guide and keep session material and keys out of logs.

Prepare your parameters
account_id
Use data.id from account creation or an account query. Account identifiers belong to the workspace selected by X-Api-Key. Get account

Request parameters

Headers

X-Api-Key
stringrequired

Workspace API key. The workspace is resolved from this header.

Content-Type
stringrequired

Use application/json when sending a JSON request body.

Path parameters

account_id
stringrequired

Identifier used in the authentication route.

Request body

session_url
string

URL or reference to an existing provider session artifact. For Facebook, session_url is required and must point to JSON with a cookies array containing c_user, xs and datr. Import success does not establish runtime readiness.

format: uri

whatsapp-protocol
object

WhatsApp Protocol session import credentials, accepted only by /v1/accounts/{account_id}/auth/session in this nested object, not provider_data. When supplied, phone, static_pub_key, static_pri_key, identity_pub_key and identity_pri_key are required. Responses never echo protocol keys or other sensitive credentials. phone checks identity consistency; protocol public and private keys are used only for upstream startup. edge_routing is injected by the platform and must not be submitted.

phone
string

When whatsapp-protocol is supplied for session import, phone is required and must be a non-empty string for identity consistency checks. Formatted input may contain spaces, hyphens, parentheses or a plus sign; the server normalizes it to a positive numeric string.

minLength: 1

platform
integer

Platform value for WhatsApp Protocol session import (int32).

format: int32

app_version
string

Application version for WhatsApp Protocol session import.

server_address
string

Provider server address for WhatsApp Protocol session import.

fallback_server_addresses[]
string[]

Fallback server addresses for WhatsApp Protocol session import.

country
string

Country code for WhatsApp Protocol session import.

device
integer

Device value for WhatsApp Protocol session import (uint32).

format: uint32

static_pub_key
string

Protocol public key; write-only.

minLength: 1

static_pri_key
string

Protocol private key; write-only.

minLength: 1

identity_pub_key
string

Identity public key; write-only.

minLength: 1

identity_pri_key
string

Identity private key; write-only.

minLength: 1

hash
string

Deprecated compatibility field; its value is ignored and not stored. Omit it.

peer_kem_public
string

Peer KEM public key; write-only.

auth_hex_data
string

Current authentication data in hexadecimal; write-only.

authhexdata
string

Deprecated legacy authentication data field in hexadecimal; write-only.

pq_handshake_mode
string

PQ handshake mode for WhatsApp Protocol session import.

use_xxkem_handshake
boolean

Whether to use the XXKEM handshake for WhatsApp Protocol session import.

tiktok
object

Only for TikTok accounts with auth_mode=session. When supplied, tiktok must be the only top-level field; only cookies and optional user_id are accepted inside it. The entire import JSON must not exceed 65536 bytes. Passing format validation does not mean valid credentials or successful authorization. QR or verification-code challenges return waiting states; session mode currently provides no interactive continuation for them. Reimporting is not guaranteed to replace an existing login or hot-swap cookies.

user_id
string

Optional compatibility field, not used for identity validation or binding; the authorization result determines the actual identity.

cookies[]
object[]

Required when tiktok is supplied: a write-only array of 1–128 cookies. Duplicate name/domain pairs are not allowed; other exported cookie attributes are preserved. Validity is determined by the login result.

minItems: 1 · maxItems: 128

name
string

Required non-empty cookie name for each TikTok cookie.

minLength: 1

value
string

Required non-empty cookie value for each TikTok cookie; write-only.

minLength: 1

domain
string

Required non-empty cookie domain for each TikTok cookie; preserve the exported value.

minLength: 1

path
string

Required path for each TikTok cookie; must start with /.

pattern: ^/

expires
number

Optional exported Unix timestamp in seconds or session-cookie marker; expiration is not checked during import.

secure
boolean

Optional exported Secure flag for the TikTok cookie.

http_only
boolean

Optional exported HttpOnly flag for the TikTok cookie.

same_site
string

Optional exported SameSite value for the TikTok cookie.

Understand the result

Read the authorization result, then check runtime_status. Session import and an active connection are different milestones.

Response pending · TikTok session

{
  "request_id": "<REQUEST_ID>",
  "data": {
    "account_id": "acc_example",
    "provider": "tiktok",
    "action": "import_session",
    "status": "pending",
    "runtime_status": "starting"
  }
}

Response authorized

{
  "request_id": "<REQUEST_ID>",
  "data": {
    "account_id": "acc_example",
    "status": "authorized"
  }
}

Response body

account_id
string

Provider account this response refers to.

status
string

Current authorization flow status, for example pending_auth, awaiting_qr_scan, awaiting_code, pending, passkey_required, passkey_pending, passkey_confirmation, passkey_confirmation_sent, authorized, or failed.

Responses

200

200 OK

Request succeeded. See the example response body.

400

Bad Request

The request body, path, or parameters are invalid.

401

Unauthorized

The X-Api-Key header is missing or invalid.

403

Forbidden

The request is authenticated but is not allowed.

404

Not Found

The requested resource was not found. Check error.code and the current operation.

409

Conflict

The requested operation conflicts with an existing provider account or resource.

500

Internal Server Error

The service encountered an unexpected error.

502

Bad Gateway

The provider adapter or upstream provider could not complete the operation.

If the request fails

Inspect HTTP status and error.code/numeric_code, and keep request_id for diagnosis. Correct invalid parameters, complete required authorization or check runtime state as appropriate. Confirm the outcome before retrying a send or another write. Error reference

Read HTTP status, error.code and error.numeric_code together in the context of the current operation. Numeric codes are strings. Keep request_id for diagnosis; it is not an idempotency key or a task identifier.

invalid_request · 10000 · 400

Check the JSON body and required fields.

What to do: Correct the parameters for this operation and channel before requesting again. Repeating an unchanged invalid request will not resolve the error.

Illustrative JSON; message varies with the actual cause · 400 · 10000
{
  "request_id": "req_example",
  "error": {
    "code": "invalid_request",
    "numeric_code": "10000",
    "message": "Invalid request parameters"
  }
}
invalid_target_workspace · 11003 · 400

The workspace override target is empty or malformed. Remove the override header and use the API key belonging to the intended workspace.

When it occurs: Applies when the request includes the X-Workspace-Id workspace override header.

What to do: Correct the parameters for this operation and channel before requesting again. Repeating an unchanged invalid request will not resolve the error.

Illustrative JSON; message varies with the actual cause · 400 · 11003
{
  "request_id": "req_example",
  "error": {
    "code": "invalid_target_workspace",
    "numeric_code": "11003",
    "message": "Invalid target workspace"
  }
}
provider_invalid_request · 30001 · 400

Check the channel-specific fields and formats.

What to do: Correct the parameters for this operation and channel before requesting again. Repeating an unchanged invalid request will not resolve the error.

Illustrative JSON; message varies with the actual cause · 400 · 30001
{
  "request_id": "req_example",
  "error": {
    "code": "provider_invalid_request",
    "numeric_code": "30001",
    "message": "Provider rejected the request"
  }
}
unsupported_action · 30005 · 400

This account action is not recognized; use a documented action.

What to do: Use a channel and action listed as supported. Repeating the same request does not add capabilities or grant beta access.

Illustrative JSON; message varies with the actual cause · 400 · 30005
{
  "request_id": "req_example",
  "error": {
    "code": "unsupported_action",
    "numeric_code": "30005",
    "message": "Action not supported"
  }
}
invalid_api_key · 11001 · 401

Check whether the API key is correct and enabled.

What to do: Keep request_id and the structured codes, and investigate the current operation before taking another action.

Illustrative JSON; message varies with the actual cause · 401 · 11001
{
  "request_id": "req_example",
  "error": {
    "code": "invalid_api_key",
    "numeric_code": "11001",
    "message": "Invalid API key"
  }
}
missing_api_key · 11000 · 401

Add the X-Api-Key header.

What to do: Keep request_id and the structured codes, and investigate the current operation before taking another action.

Example · 401 · 11000
{
  "request_id": "req_xxx",
  "error": {
    "code": "missing_api_key",
    "numeric_code": "11000",
    "message": "Missing X-Api-Key header"
  }
}
workspace_override_forbidden · 11002 · 403

The request attempts a workspace override that this API key is not allowed to use. Remove the override header and use the API key belonging to the intended workspace.

When it occurs: Applies when the request includes the X-Workspace-Id workspace override header.

What to do: Keep request_id and the structured codes, and investigate the current operation before taking another action.

Illustrative JSON; message varies with the actual cause · 403 · 11002
{
  "request_id": "req_example",
  "error": {
    "code": "workspace_override_forbidden",
    "numeric_code": "11002",
    "message": "Workspace override is not allowed"
  }
}
target_workspace_not_found · 11004 · 404

The overridden workspace was not found or is unavailable. Verify workspace ownership, remove the override header and use the intended workspace’s API key; repeated requests do not grant access.

When it occurs: Applies when the request includes the X-Workspace-Id workspace override header.

What to do: Check the target identifier, resource ownership and current workspace. Do not treat a confirmed missing or inaccessible target as a temporary service failure to retry automatically.

Illustrative JSON; message varies with the actual cause · 404 · 11004
{
  "request_id": "req_example",
  "error": {
    "code": "target_workspace_not_found",
    "numeric_code": "11004",
    "message": "Target workspace not found"
  }
}
account_already_authorized · 20016 · 409

The account has already completed authorization and this action refuses duplicate authorization. Refresh the authorization state and reuse the completed result; do not repeatedly authorize or cancel in a loop.

What to do: Keep request_id and the structured codes, and investigate the current operation before taking another action.

Illustrative JSON; message varies with the actual cause · 409 · 20016
{
  "request_id": "req_example",
  "error": {
    "code": "account_already_authorized",
    "numeric_code": "20016",
    "message": "Account is already authorized; re-authentication is not required"
  }
}
account_binding_not_found · 30006 · 409

The account has no active channel connection binding; check its status.

What to do: Query authorization and runtime status, then choose refresh, start or reconnect only when appropriate for the intended state and channel. A connection problem alone does not prove logout. Confirm running before dependent business operations.

Illustrative JSON; message varies with the actual cause · 409 · 30006
{
  "request_id": "req_example",
  "error": {
    "code": "account_binding_not_found",
    "numeric_code": "30006",
    "message": "Account is not bound to an available server"
  }
}
duplicate_provider_account · 20015 · 409

This channel identity is already connected to another account in this workspace.

What to do: Keep request_id and the structured codes, and investigate the current operation before taking another action.

Illustrative JSON; message varies with the actual cause · 409 · 20015
{
  "request_id": "req_example",
  "error": {
    "code": "duplicate_provider_account",
    "numeric_code": "20015",
    "message": "A provider account with the same identity already exists in this workspace"
  }
}
egress_configuration_pending · 20032 · 409

The platform default network configuration cannot currently be confirmed or loaded. This does not mean the account is logged out.

When it occurs: The operation uses platform-managed network capacity or a fixed default network configuration.

What to do: Keep request_id and check the account or creation result before another write. Wait for capacity or configuration recovery, or contact support. Do not repeatedly create accounts, change networks, or restart accounts automatically.

Illustrative JSON; message varies with the actual cause · 409 · 20032
{
  "request_id": "req_example",
  "error": {
    "code": "egress_configuration_pending",
    "numeric_code": "20032",
    "message": "Account network configuration is pending verification"
  }
}
provider_account_mismatch · 20017 · 409

The channel identity in the request does not match the account binding.

What to do: Keep request_id and the structured codes, and investigate the current operation before taking another action.

Illustrative JSON; message varies with the actual cause · 409 · 20017
{
  "request_id": "req_example",
  "error": {
    "code": "provider_account_mismatch",
    "numeric_code": "20017",
    "message": "Authenticated provider account does not match the bound account; re-scan with the original account"
  }
}
provider_not_ready · 30009 · 409

The connection is not ready. Check authorization and runtime_status before retrying.

What to do: Query authorization and runtime status, then choose refresh, start or reconnect only when appropriate for the intended state and channel. A connection problem alone does not prove logout. Confirm running before dependent business operations.

Illustrative JSON; message varies with the actual cause · 409 · 30009
{
  "request_id": "req_example",
  "error": {
    "code": "provider_not_ready",
    "numeric_code": "30009",
    "message": "Provider client is not ready"
  }
}
wallet_account_creation_in_progress · 20030 · 409

Another wallet account is being created in this workspace, or the target account has not finished initialization.

What to do: For a creation conflict, follow Retry-After and reuse the original Idempotency-Key if supplied. If an authorization request returns this error, query GET /v1/account-operations/{operation_id} using billing.operation_id from the creation response. Wait for data.state=SUCCEEDED, then retry the original action on the same account. billing.state=ACTIVE does not prove initialization is complete; do not create another account.

Illustrative JSON; message varies with the actual cause · 409 · 20030
{
  "request_id": "req_example",
  "error": {
    "code": "wallet_account_creation_in_progress",
    "numeric_code": "20030",
    "message": "Account creation is in progress; please wait"
  }
}
run_auth_action_failed · 20010 · 500

Run an authorization action: the authorization action failed; check the existing flow rather than assuming authorization must restart.

What to do: Query the current authorization flow and check whether user action is required. Do not start another authorization attempt merely because this request failed; do not resubmit an expired or finished session.

Illustrative JSON; message varies with the actual cause · 500 · 20010
{
  "request_id": "req_example",
  "error": {
    "code": "run_auth_action_failed",
    "numeric_code": "20010",
    "message": "Failed to run auth action"
  }
}
run_auth_action_failed · 20020 · 500

Check account_id and use an X-Api-Key for the workspace that owns the account. An account not found in this workspace cannot be accessed with this key.

When it occurs: Applies when the account is not found; the existing HTTP status and operation code are preserved, while numeric_code identifies the missing account.

What to do: Check the target identifier, resource ownership and current workspace. Do not treat a confirmed missing or inaccessible target as a temporary service failure to retry automatically.

Illustrative JSON; message varies with the actual cause · 500 · 20020
{
  "request_id": "req_example",
  "error": {
    "code": "run_auth_action_failed",
    "numeric_code": "20020",
    "message": "Account not found"
  }
}
provider_adapter_not_found · 30004 · 502

The channel service is unavailable. Check status or try again later; confirm the result before retrying writes.

What to do: Query the current authorization flow and check whether user action is required. Do not start another authorization attempt merely because this request failed; do not resubmit an expired or finished session.

Illustrative JSON; message varies with the actual cause · 502 · 30004
{
  "request_id": "req_example",
  "error": {
    "code": "provider_adapter_not_found",
    "numeric_code": "30004",
    "message": "Provider adapter unavailable"
  }
}
provider_unavailable · 30002 · 502

The channel service is unavailable. Check status or try again later; confirm the result before retrying writes.

What to do: Query the current authorization flow and check whether user action is required. Do not start another authorization attempt merely because this request failed; do not resubmit an expired or finished session.

Example · 502 · 30002
{
  "request_id": "req_example_provider_unavailable",
  "error": {
    "code": "provider_unavailable",
    "numeric_code": "30002",
    "message": "Provider service unavailable"
  }
}
provider_unavailable · 30020 · 502

A synchronous request using whatsapp-protocol identified an account login restriction with numeric_code=30020. This can affect session import, runtime, sending and contact queries while retaining the current operation’s HTTP status and code. Do not substitute the WhatsApp 20102 event contract for this channel.

What to do: Stop automatic sends and retries, and ask the user to inspect and resolve the restriction in the official WhatsApp app. Resume only after resolution and any required reauthorization. A previously running connection does not prove the restriction has cleared.

Channels: WhatsApp Protocol

Example · 502 · 30020
{
  "request_id": "req_example_account_restricted",
  "error": {
    "code": "provider_unavailable",
    "numeric_code": "30020",
    "message": "Account login is restricted. Check the official WhatsApp app for details."
  }
}