Number Masking (Privacy Proxy)
Number masking lets two parties exchange SMS messages and calls through a shared proxy number without seeing each other’s real phone number. Ride-share (driver and rider), delivery (courier and customer), marketplace (buyer and seller), and healthcare (provider and patient) flows all share the same requirement: both sides must reach each other, and neither should walk away with the other’s personal contact information. This page is the field-level reference; for the end-to-end walkthrough (create, route, terminate, and verify with webhooks), follow the masking sessions guide.Session lifecycle
Every masked conversation moves through four steps:- Create the session. Submit the two participants as E.164 numbers plus an optional TTL. You receive a session id and an allocated proxy number.
- Pool number allocation. Orbit claims a number from the shared platform pool and binds it to the session for as long as the session is active.
- Forward traffic. When a participant sends an SMS or places a call to the proxy number, Orbit matches the sender against the session’s participants and forwards to the other party with the proxy number as sender. Neither party ever sees a real number.
- Close or expire. The session ends when you close it explicitly, or when its TTL elapses and the scheduled sweeper marks it expired. Either way, the proxy number returns to the pool and can serve the next session.
Create a session
proxy_number. Hand that number to both participants and route all traffic through it:
When omitted,
ttl_minutes defaults to 60.
Pick a TTL by use case
Set the TTL to the longest window in which the two parties legitimately need to reach each other, not longer. A session left open after the job completes keeps a pool number allocated and lets either party contact the other past the point your product intends.
Two rules of thumb:
- Close explicitly when your app knows the moment of completion (trip ended, delivery confirmed). The pool number is released immediately instead of waiting for the sweep.
- Let the sweeper handle expiry when there is no clear completion event — a marketplace conversation that just goes quiet. The TTL is your cleanup, so size it like one.
List, inspect, and close sessions
limit (max 100) and follow the returned pagination.cursor for more pages. Filter by status to reconcile your order state: active sessions should map to in-flight orders, while a session your app believes is closed but reads active is a leak worth closing.
Close a session to release its proxy number immediately:
409 CONFLICT, so treat a 409 on close as “already ended” rather than as a failure to retry. You do not need to close sessions you intend to let expire - the scheduled sweeper handles those and releases the number in the same pass.
Webhooks
Register a webhook endpoint subscribed to the proxy events to track the session lifecycle and forwarding:proxy.session.created- fires when a session is created.proxy.session.closed- fires when a session is closed.proxy.message.forwarded- fires when an inbound message is matched to a session and forwarded to the counterparty.
proxy.message.forwarded to keep your own conversation view in sync: each delivery tells you the direction the message flowed, so you can render a two-sided thread without ever storing either party’s real number as the visible sender. See the webhook consumer guide for endpoint registration, signature verification, and delivery semantics.
Worked example: a ride from dispatch to drop-off
A ride-share app masks the driver–rider channel for the lifetime of one trip. 1. Dispatch matches a driver. The app creates a 45-minute session between the driver and the rider:active. A proxy.session.created webhook arrives, and the app shows both parties the proxy number +14155555678.
2. The rider texts the proxy number. The inbound message resolves to the session, the sender matches participant_b, and Orbit forwards the text to the driver with the proxy number as sender. A proxy.message.forwarded webhook records the direction. The driver replies the same way - all either side ever sees is +14155555678.
3. Drop-off completes the trip. The app closes the session:
closed. The proxy number is released back to the pool, a proxy.session.closed webhook confirms it, and neither party can reach the other afterward.
4. If the trip logic never closes — say the completion event is lost - the TTL is the backstop. At 45 minutes the sweeper marks the session expired and releases the number. The ride still ends on schedule; the close just happened later and through a different path.
Pool fairness and concurrency
Proxy sessions draw from the shared platform pool, not from the one-time free trial number assigned to your organization. There is no per-organization concurrency cap: run one session per ride, order, or listing, in parallel, without exhausting a lifetime grant. A released number - from an explicit close or a TTL sweep - returns to the pool and can be allocated to the next session, so sustained throughput scales with pool size rather than with how many sessions you have ever created.Common errors
One race to be aware of: if your completion handler fires close to the TTL boundary, the sweeper may expire the session first and your close returns 409. That outcome is equivalent - the number is released either way - so handle a 409 on close as a successful end state.