Guide

Place outbound calls

Have an agent ring your customers: appointment reminders, follow-ups, callbacks. This guide goes from a draft agent to calls placed by your own system.

1. Publish the agent

Only a published agent places calls. A draft answers 422 agent_not_published.

POST /agents/{agent_id}/publish
curl -X POST "https://api.voximate.no/public/v1/agents/7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66/publish" \
  -H "Authorization: Bearer $VOXIMATE_API_KEY"

2. Give it a number

The agent calls from one of your phone numbers, so the person called sees a number they can ring back. List your numbers, then assign one to the agent. A number answered by the agent also routes inbound calls to it.

PATCH /phone-numbers/{phone_number_id}
curl "https://api.voximate.no/public/v1/phone-numbers" \
  -H "Authorization: Bearer $VOXIMATE_API_KEY"

curl -X PATCH "https://api.voximate.no/public/v1/phone-numbers/b8f2a1c4-3d5e-4f60-8a71-92b3c4d5e6f7" \
  -H "Authorization: Bearer $VOXIMATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66"}'

3. Start the call

  • to — the number to ring, E.164 (+4712345678).
  • from — optional when the agent has exactly one number. With several, say which; with none, the API answers 422 agent_has_no_number.
  • metadata — up to 20 string values of your own, returned on the call and in every webhook about it. Use it to find your record again.
  • ring_timeout_seconds — how long to let it ring, 10 to 120. Default 30.
  • first_message — optional: what the agent says first on this call, up to 500 characters. See What the agent says first.
curl -X POST "https://api.voximate.no/public/v1/calls" \
  -H "Authorization: Bearer $VOXIMATE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
    "to": "+4712345678",
    "first_message": "Hei, dette er Nordvik Tannklinikk. Jeg ringer om timen din i morgen.",
    "metadata": { "crm_contact_id": "48213" },
    "ring_timeout_seconds": 30
  }'

What the agent says first

The agent knows it placed the call. It says who it is and why it is calling, instead of answering as if the person had rung it, and when the call ends it thanks them for the conversation rather than for calling. Its first line is, in this order:

  • first_message on this request, when you send one. Use it for what is different about each call, such as which appointment you are calling about. An empty string makes the agent wait for the person to speak first.
  • The agent’s outbound_first_message, its greeting for calls it makes. Set it with PATCH /agents/{agent_id} or under the agent’s greeting in the dashboard.
  • Otherwise its first_message, the greeting it uses when someone rings it. If that one is written for people who ring in (“thanks for calling”), set an outbound_first_message too.

4. Follow the call

The answer is 202 with the call in status queued. From there it moves to ringing, in_progress and finally completed — or no_answer, busy or failed. Subscribe to call.started, call.completed and call.failed rather than polling; see Get call results.

Calling a list

There is a limit of 10 outbound calls a minute and 500 a day per workspace by default. Send calls one by one with a pause, honour 429, and derive each Idempotency-Key from your own ids:

campaign.js
// Call a list of contacts, one at a time, staying inside the call limits.
const contacts = [
  { id: '48213', phone: '+4712345678' },
  { id: '48214', phone: '+4712345679' },
];

for (const contact of contacts) {
  const res = await fetch('https://api.voximate.no/public/v1/calls', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.VOXIMATE_API_KEY}`,
      'Content-Type': 'application/json',
      // Derived from your data: a restarted job cannot call anyone twice.
      'Idempotency-Key': `reminder-2026-10-14-${contact.id}`,
    },
    body: JSON.stringify({
      agent_id: '7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66',
      to: contact.phone,
      metadata: { crm_contact_id: contact.id, campaign: 'reminder-2026-10-14' },
    }),
  });

  if (res.status === 429) {
    const wait = Number(res.headers.get('Retry-After') ?? 60);
    await new Promise((r) => setTimeout(r, wait * 1000));
    continue; // in real code, put the contact back on the queue
  }
  const call = await res.json();
  if (!res.ok) {
    console.error(contact.id, call.error.code, call.error.message);
    continue;
  }
  console.log(contact.id, '→ call', call.id);
  await new Promise((r) => setTimeout(r, 6_000)); // 10 calls a minute
}

For large campaigns with contact lists, retries and a do-not-call list built in, use Batch Calls in the dashboard.

Rules and responsibilities

  • Norwegian emergency numbers — 110, 112 and 113 — are always refused.
  • Sales calls to consumers in Norway: check the number against Reservasjonsregisteret before you call. That check, and the right to call, are your responsibility.
  • Tell people they are speaking with an AI agent when the law or your industry requires it — put it in the agent’s greeting.
  • Answered calls count towards your plan’s minutes, like any other call.

Every request rings a real phone

Build and test against your own number. A loop with a bug can ring the same person many times; an Idempotency-Key per contact prevents it.