How it works

From one API call to two ringing phones.

Relavoi sits between your app and the carrier network. Here's what happens when your courier taps "Call customer".

01

You create a session

Your backend calls POST /v1/sessions with both parties' numbers and any metadata: order ID, zone, anything.

{ "agentPhone": "+2348031234421", "customerPhone": "+2349091231192", "gracePeriodMinutes": 15, "metadata": { "orderId": "ORD-9281" } }
02

We allocate a proxy number

An atomic Redis allocator takes a number from the pool for the requested region, guaranteeing no participant overlap with any other live session on that number.

Allocated
+234 201 342 0117

region lagos · allocated atomically

03

Either party dials the proxy

No app required. The call reaches the carrier network, arrives at Relavoi, and our router identifies the caller and bridges to the other side, against a sub-500ms p99 budget.

caller→carrier→Relavoi→callee
04

Your app hears everything

HMAC-signed webhooks and WebSocket events stream every state change: incoming, answered, ended, failed. The SDKs turn these into the in-call verification UI your customer sees.

call.incoming 14:21:28 call.answered 14:21:32 call.ended 14:23:04 92s
05

The session expires

When the job is done, a grace period covers follow-up calls, then the number returns to the pool after a cooldown. Dial it tomorrow and you reach nobody.

After expiry

"This number is no longer active. Please contact [your brand] support."

dead line · redirect · custom message

Session lifecycle

Five states. No ambiguity.

PENDING→ACTIVE→GRACE_PERIOD→EXPIREDorFAILED

Atomic allocation

Allocation and overlap checks run as one Redis Lua script. Two sessions can never race onto the same proxy for the same participant.

Provider health monitoring

A circuit breaker tracks the carrier gateway's error rate and trips on sustained failure. Secondary-provider pools are on the roadmap, not yet provisioned.

Idempotent webhooks

Duplicate carrier events never create duplicate call legs. The routing decision is cached by event ID and replayed verbatim. Failed events land in a monitored dead-letter queue.

See it with your own numbers.

Pilot partners get a provisioned number pool and can build against the sandbox first.