User guide · 4

Start a call from your agent.

Five requests cover everything: read the balance, start a call, read its state, end it, make a spare room. They use the same key and the same address as the rest of the API. Every example below was run against a test account and shows the real answer.

Checked on a live phone · 12 Oct 2026Same key as the device APIJSON in, JSON out

Authentication

Your account key, in a header.

Send the key as X-API-Key, or as Authorization: Bearer. The key decides which phones you can use; there is nothing else to configure.

shell · bashset once
export ERIUS_API="https://api.eriusphone.com"
export ERIUS_KEY="sdk_...your key..."
export ERIUS_DEVICE="your-phone-id"
shell · curlcopy-paste
curl -s -H "Authorization: Bearer $ERIUS_KEY" $ERIUS_API/whoami
responsereal output · 12 Oct 2026
{
  "tenant": "ca9a4ca3f",
  "keyId": "k2",
  "devices": [
    "ca9a4ca3f-p1"
  ]
}

Without a key, or with a wrong one:

shell · curlcopy-paste
curl -s -w "\nHTTP %{http_code}\n" $ERIUS_API/whoami
responsereal output · 12 Oct 2026
{
  "ok": false,
  "error": "unauthorized",
  "message": "missing or wrong X-API-Key",
  "requestId": "4d7c3178c05f85bf"
}

HTTP 401

With a phone id that is not yours. The answer is the same whether that phone exists or not, so ids cannot be guessed:

shell · curlcopy-paste
curl -s -w "\nHTTP %{http_code}\n" -H "X-API-Key: $ERIUS_KEY" $ERIUS_API/device/not-my-phone
responsereal output · 12 Oct 2026
{
  "ok": false,
  "error": "forbidden",
  "message": "device not found or not accessible with this key",
  "requestId": "27639e2e9f0e6aaa"
}

HTTP 403

Balance

How many minutes are left.

GET /minutes. Call it before you start a call, and after, if you want to know what the call used.

shell · curlcopy-paste
curl -s -H "X-API-Key: $ERIUS_KEY" $ERIUS_API/minutes
responsereal output · 12 Oct 2026
{
  "tenant": "ca9a4ca3f",
  "balance_minutes": 9,
  "usable_minutes": 9,
  "period_end": "2026-10-26T20:09:39Z",
  "unlimited": false,
  "expired": false
}
FieldMeaning
balance_minutesMinutes on the account.
usable_minutesMinutes a call can use right now. It is 0 when the balance is 0 or the period is over.
period_endThe minutes can be used until this time (UTC).
unlimitedtrue only for internal accounts.
expiredtrue when period_end has passed.

Start a call

One request, and you get the guest link.

POST /device/:id/calls. The phone opens a private call room and waits for the guest.

shell · curlcopy-paste
curl -s -X POST -H "X-API-Key: $ERIUS_KEY" -H "Content-Type: application/json" \
  -d '{"app":"web","max_seconds":300}' $ERIUS_API/device/$ERIUS_DEVICE/calls
responsereal output · 12 Oct 2026
{
  "ok": true,
  "device": "ca9a4ca3f-p1",
  "state": "ringing",
  "room": "GF5zB8dvSm8WPJBi79DmZ13N",
  "guest_url": "https://eriusphone.com/call/GF5zB8dvSm8WPJBi79DmZ13N?role=guest",
  "device_url": "https://eriusphone.com/call/GF5zB8dvSm8WPJBi79DmZ13N?role=device"
}
Body fieldMeaning
appMust be "web". Other values are refused; see below.
max_secondsOptional time limit for the call, 30 to 3600. Default 600 (ten minutes).
urlOptional. The device_url of a room you made earlier with POST /calls/rooms (below). Leave it out and a new room is made for you.
Answer fieldMeaning
stateringing: the phone is in the room and waits for the guest.
guest_urlSend this to the person you want to talk to. They open it and press Join call.
device_urlThe address the phone itself opened. You do not need it.
roomThe room's name. A new one for every call.
The guest page before joining, with a Join call button
What the guest sees when the link opens.

Treat the guest link like an invitation. Anyone who has it can join that one call. When the call has ended your phone is no longer in the room, so the link reaches nobody.

Call state

Ringing, connected, ended.

GET /device/:id/calls. Poll it every few seconds if you need to follow a call.

While the phone waits for the guest:

shell · curlcopy-paste
curl -s -H "X-API-Key: $ERIUS_KEY" $ERIUS_API/device/$ERIUS_DEVICE/calls
responsereal output · 12 Oct 2026
{
  "ok": true,
  "app": "web",
  "url": "https://eriusphone.com/call/GF5zB8dvSm8WPJBi79DmZ13N?role=device",
  "max_s": 300,
  "state": "ringing",
  "id": "1791836570543864383",
  "started": "2026-10-12T20:22:50Z",
  "open": "http://localhost:8971/call/GF5zB8dvSm8WPJBi79DmZ13N?role=device"
}

After the guest joined:

shell · curlcopy-paste
curl -s -H "X-API-Key: $ERIUS_KEY" $ERIUS_API/device/$ERIUS_DEVICE/calls
responsereal output · 12 Oct 2026
{
  "ok": true,
  "app": "web",
  "url": "https://eriusphone.com/call/GF5zB8dvSm8WPJBi79DmZ13N?role=device",
  "max_s": 300,
  "state": "connected",
…
stateMeaning
idleNo call. last describes the previous one.
startingThe phone is opening the room.
ringingIn the room, waiting for the guest. Not counted.
connectedGuest and persona are talking. Minutes are counted.
endedJust finished; becomes idle within seconds.

The open field is the internal address the phone uses to load the room. Ignore it.

End a call

From your side.

POST /device/:id/calls/hangup. The guest can also just leave; the call is then cleaned up by itself.

shell · curlcopy-paste
curl -s -X POST -H "X-API-Key: $ERIUS_KEY" $ERIUS_API/device/$ERIUS_DEVICE/calls/hangup
responsereal output · 12 Oct 2026
{
  "ok": true,
  "state": "ended"
}

Afterwards the state is idle and last says how the call ended:

shell · curlcopy-paste
curl -s -H "X-API-Key: $ERIUS_KEY" $ERIUS_API/device/$ERIUS_DEVICE/calls
responsereal output · 12 Oct 2026
{
  "ok": true,
  "state": "idle",
  "last": {
    "app": "web",
    "url": "https://eriusphone.com/call/GF5zB8dvSm8WPJBi79DmZ13N?role=device",
    "max_s": 300,
    "state": "ended",
    "id": "1791836570543864383",
    "started": "2026-10-12T20:22:50Z",
    "open": "http://localhost:8971/call/GF5zB8dvSm8WPJBi79DmZ13N?role=device",
    "ended": "2026-10-12T20:23:35Z",
    "reason": "hangup"
  }
}
reasonMeaning
hangupYou ended it through the API or the dashboard.
call_overThe guest hung up.
max_secondsThe time limit was reached.
minutes_exhaustedThe call minutes ran out.
session_end, stop_fileThe call ended or was stopped on our side.

The balance after this call of about half a minute. One started minute was used:

shell · curlcopy-paste
curl -s -H "X-API-Key: $ERIUS_KEY" $ERIUS_API/minutes
responsereal output · 12 Oct 2026
{
  "tenant": "ca9a4ca3f",
  "balance_minutes": 8,
  "usable_minutes": 8,
  "period_end": "2026-10-26T20:09:39Z",
  "unlimited": false,
  "expired": false
}

A spare room

A room without a call.

POST /calls/rooms only creates a room and returns its two links. Nothing is started and nothing is counted. Use it when your agent wants the guest link before the call begins: send guest_url to your guest, then start the call with device_url as the url field. We ran that sequence too; the start answers ringing, without repeating the links.

shell · curlcopy-paste
curl -s -X POST -H "X-API-Key: $ERIUS_KEY" $ERIUS_API/calls/rooms
responsereal output · 12 Oct 2026
{
  "room": "gSc3Fjm9QsAJxH9h21TGeMRj",
  "guest_url": "https://eriusphone.com/call/gSc3Fjm9QsAJxH9h21TGeMRj?role=guest",
  "device_url": "https://eriusphone.com/call/gSc3Fjm9QsAJxH9h21TGeMRj?role=device"
}

Errors

What a refused request looks like.

Errors carry a short error code and a message. The HTTP status tells you the kind.

A call is already up on this phone:

shell · curlcopy-paste
curl -s -w "\nHTTP %{http_code}\n" -X POST -H "X-API-Key: $ERIUS_KEY" \
  -H "Content-Type: application/json" -d '{"app":"web"}' $ERIUS_API/device/$ERIUS_DEVICE/calls
responsereal output · 12 Oct 2026
{
  "ok": false,
  "error": "busy",
  "message": "a call is already up on this device"
}

HTTP 409

No minutes left:

shell · curlcopy-paste
curl -s -w "\nHTTP %{http_code}\n" -X POST -H "X-API-Key: $ERIUS_KEY" \
  -H "Content-Type: application/json" -d '{"app":"web"}' $ERIUS_API/device/$ERIUS_DEVICE/calls
responsereal output · 12 Oct 2026
{
  "ok": false,
  "error": "no_minutes",
  "message": "no call minutes left on this account"
}

HTTP 402

An app other than web:

shell · curlcopy-paste
curl -s -w "\nHTTP %{http_code}\n" -X POST -H "X-API-Key: $ERIUS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"app":"whatsapp"}' $ERIUS_API/device/$ERIUS_DEVICE/calls
responsereal output · 12 Oct 2026
{
  "error": "unsupported_app",
  "message": "app must be \"web\" (WhatsApp/Telegram calls: not offered through the API yet)"
}

HTTP 400

A time limit outside 30 to 3600:

shell · curlcopy-paste
curl -s -w "\nHTTP %{http_code}\n" -X POST -H "X-API-Key: $ERIUS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"app":"web","max_seconds":5}' $ERIUS_API/device/$ERIUS_DEVICE/calls
responsereal output · 12 Oct 2026
{
  "error": "bad_max_seconds",
  "message": "max_seconds must be an integer 30..3600"
}

HTTP 400

A url that is not https://:

shell · curlcopy-paste
curl -s -w "\nHTTP %{http_code}\n" -X POST -H "X-API-Key: $ERIUS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"app":"web","url":"http://example.com/room"}' $ERIUS_API/device/$ERIUS_DEVICE/calls
responsereal output · 12 Oct 2026
{
  "error": "bad_url",
  "message": "url must be an https:// URL"
}

HTTP 400
StatuserrorWhat to do
400unsupported_app, bad_max_seconds, bad_url, bad_jsonFix the request body.
401unauthorizedSend your key.
402no_minutesAsk for minutes: Minutes and billing.
403forbiddenThe phone id is not on your account.
409busyHang up the running call first.
409calls_not_set_upThis phone has no calling setup. Open a ticket.
502, 504upstream, timeoutOur side did not answer in time. Try again; if it repeats, open a ticket.

Limits

Worth knowing before you build.

  • One call per phone at a time.
  • No call history endpoint. Only the latest call is kept, in last.
  • No relay server. Calls connect directly between the guest's browser and your phone. A guest on a network that blocks direct connections (some company networks) may not connect; see Troubleshooting.
  • Outgoing only. Calls are started by you. There are no incoming calls and no webhooks.
  • Capacity. A video call is heavy. If many calls run at once on our side, a new one can be slow to connect.

Stuck on something?

Open a ticket from your dashboard and we answer there. No key yet? Write to info@eriusphone.com.

Open a support ticket