> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# SIP credential lifecycle

> How a SIP credential is created, registered, capped, rotated, and revoked — the digest-verification handshake at the Jambonz softswitch edge, the per-credential registration and concurrency caps, and what revocation does to a live device.

# SIP credential lifecycle

A SIP credential is the account a desk phone, browser softphone, or mobile SIP app uses to register with Orbit. Each credential has a username (scoped to your organization), a password, and a set of tenant-owned limits that gate registration and calling. Manage them under **Settings → SIP credentials** in the dashboard, or through the public `POST /api/v1/voice/sip-credentials` endpoint. This page explains what the credential's lifecycle looks like from creation to revocation — how the digest verification at registration works, the per-credential caps that bound registration and calls, and what revocation does to a registered device. The inbound-route model a credential ultimately connects into lives at [Inbound voice routing](/concepts/inbound-voice-routing); the softswitch edge itself is covered by [Jambonz softswitch model](/concepts/jambonz-softswitch).

## Creation

Creating a credential generates a username scoped to your organization (`org_abc-username` shape) and a random password that is stored as the RFC 2617 A1 hash (the HA1 digest across `username:realm:password`, with a second SHA-256 variant kept for digest algorithm selection). The plaintext password is returned exactly once in the create response — `POST /api/v1/voice/sip-credentials` — and never again by any read endpoint. If the label or extension number collides with one already on your account, the create call returns 409 so you can rotate rather than stack duplicates.

The same creation step can optionally set the password to rotate later, limit outbound calls, preset media codecs, lock down to an allowed user-agent string, or constrain to specific source IPs. All of those per-credential settings adjust how the softswitch receives the device later without re-registering it.

## REGISTER handshake and digest verification

When a device sends SIP REGISTER, the Jambonz softswitch returns the stored HA1 for the username and challenges the device with a nonce. The device answers with the digest `response` — a hash over `(HA1, nonce, method, uri, …)` — and the softswitch re-computes the response before accepting the binding. Because the digest verifies at the edge, a stolen username alone cannot register without the password.

Inside Orbit a second, local verification runs whenever a credential carries a registration cap. The lookup hook re-checks the digest response against the stored HA1 before reserving a slot for the registration — so a username-guess attacker cannot fill the cap with bogus User-Agent contacts and lock out your real devices. The check fails open (returns `true` for "slot not counted") only when the digest is un-recomputable out of the packet — `*-sess` algorithms, `auth-int` quality-of-protection, or missing fields — because the softswitch itself re-verifies the digest separately and remains the authority on registration.

## Per-credential caps

Two caps bound a single credential:

* **Registration cap.** How many distinct endpoints (source IP + User-Agent pairs) may hold a live REGISTER binding at once. A keepalive REGISTER refreshes its own slot; only a genuinely new endpoint beyond the cap is rejected. Slots time out on a generous two-hour bound so a device that silently disconnects releases the slot for a replacement — but a flood of endpoints with bogus digests cannot exhaust the pool, because the local digest check above only counts verified registrations.
* **Concurrent-call cap.** How many active outbound calls the credential may hold at once, reserved atomically so simultaneous dial attempts can't both slip under the limit. A stuck call that never reports its status frees its slot after a bounded time-to-live rather than leaking the cap forever.

Both are set on the credential itself (or left unset for an unbounded default), so the platform cannot override your ceiling with a default cap you never wanted.

## Rotation

Password rotation replaces the stored HA1/HA2 pair while keeping the username and every associated ring group untouched. Rotate via `POST /api/v1/voice/sip-credentials/:id/rotate`; the old password stops authenticating immediately, so devices that were registered on it have to re-register on the next expiry cycle — typically under 60 seconds of keepalive. Riding a rotation through a rolling re-registration is the safe way to retire a compromised password.

Because rotation only touches the password, an expired or revoked credential with a rotation pending is a bad target: the credential must be re-enabled first, or a rotation on a disabled credential is wasted while the `enabled` flag remains false.

## Revocation and disable

Revoking a credential soft-deletes it: `DELETE /api/v1/voice/sip-credentials/:id` sets the deleted flag, flips the credential to `enabled = false`, and walks the audit log with the deletion event. A soft-deleted record remains visible in the audit trail, but a hard delete is deliberately not exposed — the audit history must survive a credentialing cleanup. The same entry point also supports `PATCH /api/v1/voice/sip-credentials/:id` with `enabled: false`, which disables without deleting, so a temporary suspension keeps the row and its registration-cap and route bindings intact.

The DELETE endpoint (or a `enabled=false` PATCH) immediately prevents any new SIP REGISTERs and any new inbound or outbound calls against that credential — but the currently-registered device can still hold a live binding until its next expiry. To force an active device to drop immediately, `POST /api/v1/voice/sip-credentials/:id/unregister` evicts the live REGISTER bindings right away, and the next REGISTER attempt (which the device retries by default roughly every 60 seconds) fails until the credential is re-enabled.

The audit log records the lifecycle transitions — creation, rotation, disable, deletion — with the username, label, extension, and affected entries, so a fleet that rotates or revokes credentials stays observable.

## Digest-verification at the Jambonz softswitch

The softswitch edge does not just trust the stored HA1: it verifies the digest response on every REGISTER. Orbit's API publishes the HA1 it stored at create/rotate time, Jambonz serves that HA1 in the challenge, and the digest response re-computes over `(HA1, nonce, method, uri, …)` — matching against MD5 or SHA-256 depending on what the device announced. Outbound INVITE requests from the credential also verify the caller-id ownership and edit-screen up your configured blocked-country / daily-spend caps before the call dispatches; a failure returns an accurate SIP status (403 / 402 / 480), not a silent drop. The request must still terminate on the Devotel wholesale softswitch — the credential's gateway choice is a failover preference, not a path around the termination boundary. The verification layer is described at the edge in [Jambonz softswitch model](/concepts/jambonz-softswitch), and the register-side bindings are tracked in [Hot-desking](/guides/voice-hot-desking).
