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

storage.tier_changed

Fires when the workspace recording storage tier is upgraded or downgraded.

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

storage.tier_changed fires when the workspace recording storage tier changes, either an upgrade (paid via wallet debit) or a downgrade. Note that downgrades are not refunded and take effect immediately. Use this event to update your own billing records or notify workspace members.

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

Payload

{
  "kind": "storage.tier_changed",
  "event_id": "01900000-0000-7000-8000-000000000001",
  "workspace_id": "01900000-0000-7000-8000-000000000002",
  "occurred_at": "2026-06-27T10:00:00.000Z",
  "data": {
    "previous_tier_gb": 5,
    "new_tier_gb": 25,
    "direction": "upgrade",
    "effective_at": "2026-06-27T10:00:00.000Z"
  }
}

Allowed tier_gb values: 5, 10, 25, 50, 100, 250. 5 is the free tier.

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: storage.tier_changed.

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 === "storage.tier_changed") {
    const { previous_tier_gb, new_tier_gb, direction } = event.data;
    console.log(`Storage tier ${direction}: ${previous_tier_gb}GB -> ${new_tier_gb}GB`);
    // update subscription records, notify admins...
  }
  return new Response("OK", { status: 200 });
}

Next steps

  • Subscribe via POST /v1/webhooks with events: ["storage.tier_changed"].
  • See Storage API for tier management endpoints.
  • See Webhook concepts for signature verification details.