Skip to content

API Token (machine-to-machine)

API tokens are issued to machine clients (CRM backends, dialer engines, integration services) that call the Zorio API without being tied to a user session. They suit server-to-server traffic, cron jobs, and integration microservices.

How they differ from Bearer (user session) tokens

PropertyBearer (user session)API Token (machine)
Tied toOne specific userOne app / service
When the user logs outToken is invalidatedStill alive
When the user changes their passwordStill aliveStill alive
Audit log entriesUse user.usernameUse the application name
Best forApps with users (frontend, mobile)Server-to-server / cron

TIP

Both schemes use the same Authorization: Bearer <token> header — they're distinguished by how they're issued and how they show up in audit logs, not by token format.

Create an API token

Admins only

API tokens can only be created by an account admin through the Admin Console. There is no public API to self-issue tokens (this prevents a CRM from cloning its own tokens).

Steps

  1. Go to Admin Console → Settings → API Tokens.
  2. Pick the Machine Tokens tab (different from "User Tokens").
  3. Click Create Machine Token:
    • Name — e.g. "CRM Salesforce Production", "Dialer Engine v2".
    • Permission scope — pick specific permissions (e.g. pbx_api_access, telesales_create_lead).
    • IP whitelist (optional) — only accept requests from listed IPs.
    • Expiration (optional) — auto-expire after N days.
  4. The system generates the token → copy it once, immediately.

Use an API token

Same as Bearer (user session) — just add Authorization: Bearer <token> to every request.

bash
curl -X POST 'https://app.zorio.vn/api/pbx/calls/click-to-call' \
  -H 'Authorization: Bearer <YOUR_MACHINE_TOKEN>' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{"from_extension":"1001","to_phone":"0987654321"}'

Permission scope

An API token has a narrower scope than a user — it can only perform actions listed in the permissions selected at creation time.

Common scopes:

ScopeAllows
pbx_api_accessEvery /api/pbx/* endpoint
manage_caller_idsCRUD on caller IDs and groups
telesales_api_accessRead/write Telesales campaigns and leads
autocall_api_accessRead/write AutoCall campaigns and leads
view_all_cdrRead CDR for the entire account
view_team_cdrRead CDR only within a team

To inspect the current token's permissions:

GET /api/auth/me
Authorization: Bearer <token>

Response 200 returns a permissions[] array.

IP whitelist

When a token is created with an IP whitelist:

  • Requests from any IP not in the list → HTTP 403 with body { "message": "Forbidden: IP not whitelisted." }.
  • 0.0.0.0/0 = accept every IP (the default).
  • CIDR ranges are supported (e.g. 203.0.113.0/24).

Load balancer note

If your app sits behind a load balancer / nginx proxy — Zorio reads the IP from the X-Forwarded-For header (the client, proxy1, proxy2 chain). Your LB must forward the real client IP correctly.

Audit log

Every request made with an API token is logged with:

FieldDescription
token_nameToken name (e.g. "CRM Salesforce Production")
ipSource IP
endpointMethod + path
statusHTTP response status
atTimestamp

Browse at Admin Console → Audit Log → API Token Activity.

Rotate tokens

For security, rotate tokens regularly (every 90 days is the recommended cadence):

  1. Go to Admin Console → API Tokens → click Rotate next to the token.
  2. The system mints a new token — copy it.
  3. Deploy the new token to your app.
  4. Verify the app is healthy with the new token.
  5. Revoke the old token after you've confirmed.

Don't rotate two tokens at once

If your app uses several tokens (e.g. LB → N replicas), rotate them one at a time, not simultaneously, so you keep a rollback path if something breaks.

Revoke

When a token is compromised or no longer needed — Admin Console → API Tokens → Revoke. Any request with the token after revocation → HTTP 401.

Revoke immediately on suspected leak

  • Code with the token accidentally committed to a public git repo.
  • A server holding the token was hacked.
  • A staff member with token-creation rights left the company.

Revoke now, don't wait for an investigation. Mint a new token and redeploy.

Add the token to CI/CD

ToolHow to store the token
GitHub ActionsRepository secret → ZORIO_API_TOKEN
GitLab CICI/CD Variables (Masked + Protected)
JenkinsCredentials → Secret Text
VaultPath secret/zorio/api-token → fetch at deploy time
KubernetesSecret → mount as env var on the pod

DO NOT echo tokens to build logs. Most CI tools have a "masked output" flag — enable it.

Sample server-to-server (cron lead import)

js
// cron-job.js — runs every 5 minutes
const axios = require('axios');

const api = axios.create({
  baseURL: 'https://app.zorio.vn/api',
  headers: {
    Authorization: 'Bearer ' + process.env.ZORIO_TOKEN,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  timeout: 30_000,
});

async function syncLeads() {
  const crmLeads = await fetchFromCRM();
  for (const lead of crmLeads) {
    try {
      await api.post(`/telesales/campaigns/${lead.campaign_id}/leads`, {
        phone: lead.phone,
        custom_fields: lead.fields,
      });
    } catch (err) {
      if (err.response?.status === 422) {
        console.error('Lead invalid:', lead, err.response.data.errors);
      } else {
        throw err;
      }
    }
  }
}

syncLeads().catch(console.error);

Cấp phép theo điều khoản sử dụng của Zorio.