sautikit
PricingDevelopersBlogAbout
Sign inStart building
Guides
  • Browser Calling with WebRTC
  • Build a Call Center with Conferences
  • Build a Voice IVR
  • Claim and Route a Number
  • Quickstart: Place a Call
  • Record and Stream to S3
  • Verify Webhook Signatures
Concepts
  • Browser Calling with WebRTC
  • Calls
  • Phone Numbers
  • Voice Actions DSL
  • Wallet and Billing
  • Webhooks
  • Workspaces
Voice Actions
  • Conference
  • Dial
  • GetDigits
  • Hangup
  • Play
  • Record
  • Redirect
  • Reject
  • Say
Webhooks
  • call.answered
  • call.completed
  • call.failed
  • call.recording.ready
  • call.started
  • number.provisioned
  • number.released
  • storage.tier_changed
  • wallet.low_balance
  • wallet.top_up
SDKs
  • Go SDK
  • Node.js SDK
  • PHP SDK
  • Python SDK
Errors
  • account.suspended
  • accounts.admin_required
  • accounts.last_owner
  • accounts.remove_denied
  • accounts.role_change_denied
  • accounts.write_denied
  • api_key.already_revoked
  • api_key.expired
  • api_key.invalid
  • api_key.name_required
  • api_key.not_found
  • api_key.revoked
  • api_key.scope_denied
  • api_key.scope_invalid
  • audit.invalid_action_kind
  • auth.admin_required
  • auth.cannot_unlink_only_auth
  • auth.email_taken
  • auth.google_exchange_failed
  • auth.google_not_configured
  • auth.google_state_mismatch
  • auth.invite_email_mismatch
  • auth.no_workspace
  • auth.session_invalid
  • auth.token_expired
  • auth.token_invalid
  • auth.token_used
  • auth.workspace_forbidden
  • calls.events_failed
  • calls.get_failed
  • calls.list_failed
  • calls.not_found
  • calls.recording_expired
  • calls.recording_failed
  • calls.recording_not_found
  • calls.stats_failed
  • currency.unsupported
  • idempotency.conflict
  • internal_error
  • invitations.not_found
  • invite_requires_login
  • method_not_allowed
  • mpesa.unavailable
  • not_found
  • numbers.already_claimed
  • numbers.invalid_routing_url
  • numbers.not_assigned
  • numbers.not_found
  • numbers.price_missing
  • numbers.retired
  • numbers.series_invalid
  • numbers.series_not_active
  • numbers.sip_config_unavailable
  • numbers.sip_credentials.already_revoked
  • numbers.sip_credentials.not_found
  • numbers.sip_token_unavailable
  • numbers.suffix_collision
  • numbers.wallet_unavailable
  • paystack.unavailable
  • pbx.body_read_failed
  • pbx.ingest_failed
  • pbx.payload_decode_failed
  • pbx.resolve_failed
  • pbx.unknown_workspace
  • provider.has_active_series
  • provider.invalid_credentials
  • storage.tier_invalid
  • storage.tier_switch_failed
  • topup.not_found
  • validation.bad_request
  • validation.invalid_cursor
  • wallet.adjustment_invalid_kind
  • wallet.alert_subscriber_exists
  • wallet.alert_subscriber_invalid_email
  • wallet.alert_subscriber_not_found
  • wallet.alert_subscribers_max
  • wallet.currency_mismatch
  • wallet.insufficient_funds
  • wallet.invalid_amount
  • wallet.not_found
  • wallet.topup_below_minimum
  • webhooks.create_failed
  • webhooks.delete_failed
  • webhooks.deliver.secret_unset
  • webhooks.delivery_not_retryable
  • webhooks.dispatcher_unavailable
  • webhooks.event_unsupported
  • webhooks.list_failed
  • webhooks.not_found
  • webhooks.patch_failed
  • webhooks.rotate_secret_failed
Changelog
  • 2026-06-15: Public Pricing Endpoint
  • 2026-06-20: WebRTC SIP Token (HS256 5-min TTL + Key Rotation)
  • 2026-06-27: sautikit.com Launch
  • Inbound voice is now free; outbound drops to KES 3/min

number.released

Fires when a phone number is released from the workspace and returned to inventory.

2026-06-27

Next Steps

  • WebhooksSautikit webhooks deliver signed JSON payloads to your HTTPS endpoint. Delivery is at-least-once with an 8-attempt exponential backoff schedule. Verify the HMAC-SHA256 signature on every request.
sautikit

Programmable voice infrastructure for Africa. Buy numbers, place calls, and bill per second, all in KES, via API.

Product

NumbersCalls & routingRecordingsWallet & billingPricing

Developers

DocumentationAPI referenceQuickstartAI promptChangelog

Company

AboutBlogCareersConsole

© 2026 Sautikit. All rights reserved.

Sautikit provides voice API services for application developers. Numbers provisioned on this platform are not configured for emergency calling (e.g. 999 / 112). Do not use Sautikit numbers as a replacement for a primary phone line.

Summary

number.released fires when a DID is unassigned from the workspace and returned to inventory. This can be triggered by an explicit release request, trial expiry termination, or an admin action. Use this event to clean up routing configuration, remove the number from internal phone books, and stop billing it in your own systems.

This event is subscribable via workspace webhooks (POST /v1/webhooks).

Payload

{
  "kind": "number.released",
  "event_id": "01900000-0000-7000-8000-000000000001",
  "workspace_id": "01900000-0000-7000-8000-000000000002",
  "occurred_at": "2026-06-27T10:00:00.000Z",
  "data": {
    "number_id": "01900000-0000-7000-8000-000000000003",
    "e164": "+254700000001",
    "country_code": "KE",
    "release_reason": "explicit",
    "released_at": "2026-06-27T10:00:00.000Z"
  }
}

Possible release_reason values: explicit (caller-initiated), trial_expired, admin_released.

Headers

Every webhook delivery includes the following request headers:

HeaderDescription
X-Sautikit-SignatureHMAC-SHA256 of the raw body, hex-encoded. Verify with your subscription secret.
X-Sautikit-Idempotency-KeyUnique delivery ID for deduplication.
X-Sautikit-EventLiteral event kind: number.released.

Delivery semantics

  • At-least-once: The dispatcher may deliver the same event more than once. Deduplicate using event_id or the X-Sautikit-Idempotency-Key header.
  • Retry schedule: Up to 5 attempts with exponential backoff (1-2-4-8-16 seconds). After exhausting attempts the delivery row moves to dead_letter.
  • Timeout: Your endpoint must respond within 10 seconds. A non-2xx response or timeout counts as a failed attempt.

Example handler

import { createHmac } from "node:crypto";
 
export async function POST(req) {
  const sig = req.headers["x-sautikit-signature"];
  const body = await req.text();
  const expected = createHmac("sha256", process.env.WEBHOOK_SECRET)
    .update(body)
    .digest("hex");
  if (sig !== expected) return new Response("Forbidden", { status: 403 });
 
  const event = JSON.parse(body);
  if (event.kind === "number.released") {
    const { number_id, e164, release_reason } = event.data;
    console.log(`Number ${e164} released (${release_reason}): ${number_id}`);
    // remove from routing config, update CRM...
  }
  return new Response("OK", { status: 200 });
}

Next steps

  • Subscribe via POST /v1/webhooks with events: ["number.released"].
  • Pair with number.provisioned to track full number lifecycle.
  • See Numbers API for release endpoint documentation.