KeepMyNumber
Home Sign in

Webhook event examples

Every example on this page is a real delivery captured from a live run of the platform — a full port-in (including a review rejection and fix), a draft deletion, a cancellation, and every port-out outcome. What you see here is exactly what your endpoint receives.

How to register endpoints, verify the Porting-Signature header, and how retries work is covered in Webhooks. This page is the payload catalog.

The envelope

Every delivery is an HTTP POST with the same three headers and the same four-field body — only payload varies by event type:

POST /hooks/porting HTTP/1.1
Content-Type: application/json
Porting-Event-Id: b25bb1ba-f880-4ea4-825a-32c465cab8e9
Porting-Event-Type: porting_order.created
Porting-Signature: t=1788072097,v1=4021b9617fb3cc58de9fca72d333708e6c0d6592c497c90bc3c768ca66fa19b6

{"id": "...", "type": "...", "created_at": "...", "payload": {...}}
  • id (= Porting-Event-Id) is your deduplication key — retries can deliver the same event twice.
  • created_at is UTC (no timezone suffix).
  • Delivery order is not guaranteed under retries. When two events describe the same change (e.g. a field rejection + the order moving to rejection), don't assume which arrives first.

Port-in lifecycle

porting_order.created

One per draft order. A single POST /v2/porting_orders can produce several of these (see porting_order.split below) — all sharing a batch_id.

{
  "id": "b25bb1ba-f880-4ea4-825a-32c465cab8e9",
  "type": "porting_order.created",
  "created_at": "2026-08-30T06:41:36.875656",
  "payload": {
    "porting_order": {
      "id": "f3a2f1ef-e191-4997-946a-1200c85a4905",
      "batch_id": "01e38948-7dc9-49cd-9713-985b0b9b7434",
      "status": "draft",
      "closed_by": null,
      "provider_status": null,
      "country_code": "GB",
      "number_type": "mobile",
      "customer_reference": "crm-1042",
      "requirements_status": false,
      "foc_requested": null,
      "foc_actual": null,
      "forwarded_at": null,
      "phone_numbers": [
        "+447912345678",
        "+447912345679",
        "+447912345680",
        "+447912345681"
      ]
    }
  }
}

This porting_order snapshot is the same one carried by every porting_order.status_changed event.

porting_order.split

Fired (in addition to one created per order) when one create request becomes several orders — numbers spanning countries or number types. The request above contained 4 GB mobile numbers and 1 US local number. The same event is also fired later, at forward time, if the carrier splits an order further (reason: "the provider split the order (e.g. by losing carrier)"); those sibling orders appear already submitted.

{
  "id": "60ffa170-955e-497c-b1c1-8923e7b7cc80",
  "type": "porting_order.split",
  "created_at": "2026-08-30T06:41:36.878541",
  "payload": {
    "batch_id": "01e38948-7dc9-49cd-9713-985b0b9b7434",
    "porting_order_ids": [
      "f3a2f1ef-e191-4997-946a-1200c85a4905",
      "fb1be827-98f7-44a2-b9c7-93a0d065101e"
    ],
    "reason": "numbers span multiple countries or number types"
  }
}

loa.signed

The end user's drawn signature was submitted (PATCH …/requirements/loa) and the platform rendered and stored the signed LOA PDF. document_id is the signed PDF (downloadable via GET /v2/documents/{id}/download); document_sha256 lets you prove the file never changed.

{
  "id": "891ae5bc-e1ea-45c7-9c6f-1fb33061fdf4",
  "type": "loa.signed",
  "created_at": "2026-08-30T06:41:37.249106",
  "payload": {
    "document_id": "9f70f594-9b75-4bf9-beaf-b6e170ee6441",
    "signature_id": "6754eaa4-1ccb-4bba-a090-86a620b8575a",
    "order_id": "f3a2f1ef-e191-4997-946a-1200c85a4905",
    "template": {
      "country_code": "GB",
      "provider_slug": null,
      "number_type": null,
      "version": 2
    },
    "signer_name": "Jane Doe",
    "signer_email": "jane.doe@acme.example",
    "locale": "en",
    "phone_numbers": [
      "+447912345678",
      "+447912345679",
      "+447912345680",
      "+447912345681"
    ],
    "document_sha256": "aa30ff94966d94ccb68f94f2087ebc01a406112e575a7dbdeb311c3ea4ca6225"
  }
}

porting_order.status_changed

Fired on every lifecycle move — this is the event to build your state machine on. The full status table lives in the Webhooks guide. Four captured examples from the same order's journey:

Submitted for review (POST …/submit parks the order in in_review):

{
  "id": "ccecb33e-9073-4555-b647-d25a862103ce",
  "type": "porting_order.status_changed",
  "created_at": "2026-08-30T06:41:37.273705",
  "payload": {
    "porting_order": {
      "id": "f3a2f1ef-e191-4997-946a-1200c85a4905",
      "batch_id": "01e38948-7dc9-49cd-9713-985b0b9b7434",
      "status": "in_review",
      "closed_by": null,
      "provider_status": null,
      "country_code": "GB",
      "number_type": "mobile",
      "customer_reference": "crm-1042",
      "requirements_status": false,
      "foc_requested": null,
      "foc_actual": null,
      "forwarded_at": null,
      "phone_numbers": [
        "+447912345678",
        "+447912345679",
        "+447912345680",
        "+447912345681"
      ]
    },
    "previous_status": "draft",
    "new_status": "in_review"
  }
}

Port date confirmed — there is no separate FOC event: the confirmed date arrives on this event as foc_actual:

{
  "id": "17257f6e-bd7a-4372-8603-ab8c3a9a039c",
  "type": "porting_order.status_changed",
  "created_at": "2026-08-30T06:41:37.545711",
  "payload": {
    "porting_order": {
      "id": "f3a2f1ef-e191-4997-946a-1200c85a4905",
      "batch_id": "01e38948-7dc9-49cd-9713-985b0b9b7434",
      "status": "foc_scheduled",
      "closed_by": null,
      "provider_status": "foc-date-confirmed",
      "country_code": "GB",
      "number_type": "mobile",
      "customer_reference": "crm-1042",
      "requirements_status": true,
      "foc_requested": null,
      "foc_actual": "2026-09-11T09:00:00+00:00",
      "forwarded_at": "2026-08-30T06:41:37.409185",
      "phone_numbers": [
        "+447912345678",
        "+447912345679",
        "+447912345680",
        "+447912345681"
      ]
    },
    "previous_status": "in_process",
    "new_status": "foc_scheduled"
  }
}

Port completed — the numbers are live on the platform (one number.activated per number follows):

{
  "id": "4dcf1d7b-c549-46c6-8310-bde3d78d134c",
  "type": "porting_order.status_changed",
  "created_at": "2026-08-30T06:41:37.603132",
  "payload": {
    "porting_order": {
      "id": "f3a2f1ef-e191-4997-946a-1200c85a4905",
      "batch_id": "01e38948-7dc9-49cd-9713-985b0b9b7434",
      "status": "completed",
      "closed_by": null,
      "provider_status": "ported",
      "country_code": "GB",
      "number_type": "mobile",
      "customer_reference": "crm-1042",
      "requirements_status": true,
      "foc_requested": null,
      "foc_actual": "2026-09-11T09:00:00",
      "forwarded_at": "2026-08-30T06:41:37.409185",
      "phone_numbers": [
        "+447912345678",
        "+447912345679",
        "+447912345680",
        "+447912345681"
      ]
    },
    "previous_status": "activating",
    "new_status": "completed"
  }
}

Cancelled — terminal close. closed_by tells you who ended it: customer (you), provider (final refusal by the losing carrier), or ops. This one was a customer cancelling a never-forwarded draft, so it went straight to cancelled without cancel_pending:

{
  "id": "6d5f06ab-77e1-4861-8a28-a7d5e85f3f42",
  "type": "porting_order.status_changed",
  "created_at": "2026-08-30T06:41:37.747914",
  "payload": {
    "porting_order": {
      "id": "fb1be827-98f7-44a2-b9c7-93a0d065101e",
      "batch_id": "01e38948-7dc9-49cd-9713-985b0b9b7434",
      "status": "cancelled",
      "closed_by": "customer",
      "provider_status": null,
      "country_code": "US",
      "number_type": "local",
      "customer_reference": "crm-1042",
      "requirements_status": false,
      "foc_requested": null,
      "foc_actual": null,
      "forwarded_at": null,
      "phone_numbers": [
        "+14155552671"
      ]
    },
    "previous_status": "draft",
    "new_status": "cancelled"
  }
}

porting_order.requirement_updated

Our review desk (or the losing carrier) verified one specific field. Two variants — approved:

{
  "id": "5bcf7f44-099c-4d31-9c8d-c4663f18507a",
  "type": "porting_order.requirement_updated",
  "created_at": "2026-08-30T06:41:37.300008",
  "payload": {
    "porting_order_id": "f3a2f1ef-e191-4997-946a-1200c85a4905",
    "requirement": {
      "slug": "account_number",
      "status": "approved"
    }
  }
}

…and rejected, with the reason. A rejected field also moves the whole order to rejection, so a porting_order.status_changed arrives alongside this event. Fix the named field (PATCH …/requirements/{slug}) and resubmit:

{
  "id": "f880cf85-bd99-4c3c-99e2-6c35b1ac997c",
  "type": "porting_order.requirement_updated",
  "created_at": "2026-08-30T06:41:37.321486",
  "payload": {
    "porting_order_id": "f3a2f1ef-e191-4997-946a-1200c85a4905",
    "requirement": {
      "slug": "recent_invoice",
      "status": "requirement-info-exception",
      "reason": "The invoice is older than 30 days — upload the most recent one."
    }
  }
}

porting_order.new_comment

Our ops team or the carrier left a note on your order. author is ops or provider (your own comments are not echoed back).

{
  "id": "677f0bce-a654-47aa-b372-ca26422094a0",
  "type": "porting_order.new_comment",
  "created_at": "2026-08-30T06:41:37.388610",
  "payload": {
    "porting_order_id": "f3a2f1ef-e191-4997-946a-1200c85a4905",
    "comment": {
      "id": "c3e67e84-dc0b-410b-bddb-44fcb502e9f1",
      "author": "ops",
      "body": "Reviewed and verified — forwarding to the carrier now."
    }
  }
}

number.activated

A ported number went live in your numbers registry — one event per number, right after the order's completed event. status is active when the order carried a routing_config, otherwise active_unconfigured (as here — configure routing via PATCH /v2/numbers/{id}).

{
  "id": "cbc11fbd-3979-482e-9635-9e4471f95c7a",
  "type": "number.activated",
  "created_at": "2026-08-30T06:41:37.598160",
  "payload": {
    "number": {
      "id": "a21ba2f8-0a06-4c0a-baa2-ae536f3b4f62",
      "phone_number": "+447912345678",
      "status": "active_unconfigured"
    },
    "porting_order_id": "f3a2f1ef-e191-4997-946a-1200c85a4905"
  }
}

number.forwarding_updated

The call-forwarding rules for a number changed (PUT or DELETE /v2/numbers/{id}/call_forwarding — see Call forwarding). null rule = cleared.

{
  "id": "5c1d2f7e-93aa-40cb-8d21-6a5b7f0c4e19",
  "type": "number.forwarding_updated",
  "created_at": "2026-09-06T09:00:00.120450",
  "payload": {
    "number": {
      "id": "a21ba2f8-0a06-4c0a-baa2-ae536f3b4f62",
      "phone_number": "+447912345678"
    },
    "forwarding": {
      "forward_all": {"type": "sip", "sip_endpoint": "alice@pbx.example.com"},
      "on_missed": {"type": "number", "phone_number": "+14155552671"}
    },
    "changed_by": "customer"
  }
}

porting_order.deleted

A never-submitted draft was hard-deleted (DELETE /v2/porting_orders/{id}). The payload is a final tombstone — the order id will 404 afterwards.

{
  "id": "beec8241-3c0e-4b9c-abd9-516cf5c49324",
  "type": "porting_order.deleted",
  "created_at": "2026-08-30T06:41:37.720118",
  "payload": {
    "porting_order_id": "2899790b-b9de-4bf2-8154-7cea3c76160e",
    "batch_id": "511384ec-91a5-4ef1-b007-e7a06840120b",
    "country_code": "GB",
    "number_type": "mobile",
    "customer_reference": "crm-1043",
    "phone_numbers": [
      "+447912345690"
    ]
  }
}

Port-outs

port_out.created

Another carrier asked to take one of your numbers. Always the first event of a port-out, whatever your policy. deadline_at is the decision deadline (24h).

{
  "id": "584b82db-1bd8-4ae5-b4b6-4fb4454948c1",
  "type": "port_out.created",
  "created_at": "2026-08-30T06:43:40.326318",
  "payload": {
    "port_out": {
      "id": "d3693395-775f-49bb-8127-80f1d0691099",
      "phone_number": "+447912345678",
      "status": "pending",
      "gaining_carrier": "Vodafone UK",
      "deadline_at": "2026-08-31T06:43:40.322883+00:00",
      "reason": null
    }
  }
}

port_out.status_changed

What happens next depends on your account's port_out_policy. All four captured outcomes:

Decision required (manual policy) — the only variant that needs action from you. Decide before deadline_at via POST /v2/port_out_requests/{id}/approve or …/reject:

{
  "id": "b9d51f7e-688f-433a-a242-dc73bd35c6a5",
  "type": "port_out.status_changed",
  "created_at": "2026-08-30T06:43:40.404817",
  "payload": {
    "port_out": {
      "id": "e7f24219-f826-4e79-a93f-a1fbf704d22b",
      "phone_number": "+447912345679",
      "status": "action_required",
      "gaining_carrier": "O2 UK",
      "deadline_at": "2026-08-31T06:43:40.403453+00:00",
      "reason": null
    },
    "action": "decision_required"
  }
}

Approved — by you, or automatically under the auto_approve policy when the gaining carrier presented the correct port-out PIN:

{
  "id": "ee705f5c-982f-4e35-8b6c-c73dc0145d98",
  "type": "port_out.status_changed",
  "created_at": "2026-08-30T06:43:40.333662",
  "payload": {
    "port_out": {
      "id": "d3693395-775f-49bb-8127-80f1d0691099",
      "phone_number": "+447912345678",
      "status": "approved",
      "gaining_carrier": "Vodafone UK",
      "deadline_at": "2026-08-31T06:43:40.322883+00:00",
      "reason": null
    }
  }
}

Rejected — reason is always present (it's mandatory when rejecting; automatic rejections carry pin_mismatch):

{
  "id": "46f67a5f-4369-4416-b0af-3169fd11509d",
  "type": "port_out.status_changed",
  "created_at": "2026-08-30T06:43:40.530320",
  "payload": {
    "port_out": {
      "id": "c3f8aa6b-d242-4a35-9abe-e3b6c81b2118",
      "phone_number": "+447912345680",
      "status": "rejected",
      "gaining_carrier": "EE",
      "deadline_at": "2026-08-31T06:43:40.489105",
      "reason": "Our customer did not authorize this transfer."
    }
  }
}

Expired — the decision deadline passed without a decision:

{
  "id": "266b53d0-318e-4361-8174-cc5fd6ceddb2",
  "type": "port_out.status_changed",
  "created_at": "2026-08-30T06:44:05.159797",
  "payload": {
    "port_out": {
      "id": "bc4be516-9387-4e8f-a9b2-78a9c7b7afa5",
      "phone_number": "+447912345681",
      "status": "expired",
      "gaining_carrier": "Three UK",
      "deadline_at": "2026-08-30T05:44:05.156408+00:00",
      "reason": null
    },
    "note": "expired without a decision"
  }
}

number.ported_out

The port-out completed: the number has left the platform and its routing was cleared. Note there is no port_out.status_changed with status completed — this event is the completion signal.

{
  "id": "5f5ca24b-c23b-43e8-9a33-975aa55d9158",
  "type": "number.ported_out",
  "created_at": "2026-08-30T06:43:40.376253",
  "payload": {
    "number": {
      "id": "a21ba2f8-0a06-4c0a-baa2-ae536f3b4f62",
      "phone_number": "+447912345678"
    },
    "port_out_id": "d3693395-775f-49bb-8127-80f1d0691099"
  }
}

number.removed

A platform operator removed the number from the registry (rare: test resets or support interventions). Its SMS history is deleted with it; wallet history is kept. The number can be ported in again afterwards.

{
  "id": "8c1f0f4e-3d2a-4b9d-9f27-6f4f4f1b2a10",
  "type": "number.removed",
  "created_at": "2026-09-06T20:15:02.114520",
  "payload": {
    "number": {
      "id": "a21ba2f8-0a06-4c0a-baa2-ae536f3b4f62",
      "phone_number": "+16605550123"
    },
    "removed_by": "ops",
    "messages_deleted": 4
  }
}

number.provider_changed

A platform operator corrected which carrier hosts the number (rare: a number that was routed through the wrong provider at port time). Your forwarding rules are unchanged and are re-applied to the right carrier; nothing to do on your side unless you mirror the hosting provider.

{
  "id": "5b7d3c2e-9a41-4f60-8c1d-2e7f0a9b6c33",
  "type": "number.provider_changed",
  "created_at": "2026-09-10T09:12:44.501233",
  "payload": {
    "number": {
      "id": "a21ba2f8-0a06-4c0a-baa2-ae536f3b4f62",
      "phone_number": "+12165455345"
    },
    "previous_provider": "us_carrier",
    "provider": "telnyx",
    "changed_by": "ops"
  }
}

SMS

Once a number is active you can message with it — see Sending SMS. All four sms.* events carry the same message snapshot (the shape of GET /v2/messages/{id}).

sms.sent

The provider accepted your outbound message (POST /v2/messages). cost is the price charged: the per-segment rate × segments.

{
  "id": "77f3f3c4-8a4e-4b52-9f0e-40b1f3f0e7ac",
  "type": "sms.sent",
  "created_at": "2026-09-04T10:15:00.412331",
  "payload": {
    "message": {
      "id": "3b8b02de-77e6-44a5-b0e5-30f1f4bfa2ad",
      "direction": "outbound",
      "from_number": "+447912345678",
      "to_number": "+14155552671",
      "text": "Your verification code is 482913",
      "segments": 1,
      "status": "queued",
      "destination_country": "US",
      "cost": 0.0079,
      "currency": "USD",
      "error": null,
      "created_at": "2026-09-04T10:15:00.408516+00:00"
    }
  }
}

sms.delivered

The destination handset confirmed receipt (delivery receipt from the carrier). Not every network sends confirmations — a message can stay sent forever and still have arrived.

{
  "id": "b1cf9c93-64b4-4a1a-a1ce-8a17d9e5b1de",
  "type": "sms.delivered",
  "created_at": "2026-09-04T10:15:04.102844",
  "payload": {
    "message": {
      "id": "3b8b02de-77e6-44a5-b0e5-30f1f4bfa2ad",
      "direction": "outbound",
      "from_number": "+447912345678",
      "to_number": "+14155552671",
      "text": "Your verification code is 482913",
      "segments": 1,
      "status": "delivered",
      "destination_country": "US",
      "cost": 0.0079,
      "currency": "USD",
      "error": null,
      "created_at": "2026-09-04T10:15:00.408516+00:00"
    }
  }
}

sms.failed

Sending or delivery failed; error carries the provider's explanation.

{
  "id": "5f9a2e0d-40e3-4b7f-9a91-6cf1a1a7f2b0",
  "type": "sms.failed",
  "created_at": "2026-09-04T10:16:11.837190",
  "payload": {
    "message": {
      "id": "9d5c1f27-8e34-4f7a-9df1-2f60b6f7a8ee",
      "direction": "outbound",
      "from_number": "+447912345678",
      "to_number": "+14155552672",
      "text": "Your verification code is 550128",
      "segments": 1,
      "status": "failed",
      "destination_country": "US",
      "cost": 0.0079,
      "currency": "USD",
      "error": "Recipient unreachable",
      "created_at": "2026-09-04T10:16:10.221547+00:00"
    }
  }
}

sms.received

Someone texted one of your platform numbers. Inbound messages are free — cost and currency are null.

{
  "id": "0a6ff7e2-13b4-4b6a-8f2f-4a1f6f0b6a90",
  "type": "sms.received",
  "created_at": "2026-09-04T10:18:22.905311",
  "payload": {
    "message": {
      "id": "c4f0b7a1-2d3e-4f5a-8b9c-0d1e2f3a4b5d",
      "direction": "inbound",
      "from_number": "+14155552671",
      "to_number": "+447912345678",
      "text": "Thanks, got it!",
      "segments": 1,
      "status": "received",
      "destination_country": null,
      "cost": null,
      "currency": null,
      "error": null,
      "created_at": "2026-09-04T10:18:22.901276+00:00"
    }
  }
}

Calls

Every forwarded call to one of your numbers produces a call.forwarded event when it is sent to the target, and one closing event — call.completed (answered) or call.missed (never answered). All three share call_id, number, from, provider and provider_call_ref; forwarded_by says who did the forwarding: "platform" (we routed the call ourselves, the normal case for Telnyx-hosted numbers) or "carrier" (the hosting carrier forwarded it natively and reported it to us). See Call forwarding — Call notifications.

call.forwarded (platform-routed, primary target)

A call reached +12165455345; the platform sent it to the configured SIP endpoint without answering the caller. The caller hears the target ring.

{
  "id": "0d6b3a1e-8f2c-4f7a-9c1d-5e2b7a9f3c40",
  "type": "call.forwarded",
  "created_at": "2026-09-11T09:24:26.912004",
  "payload": {
    "call_id": "4b1c9f02-3c7e-4d1a-9b0e-8a2f1c6d7e55",
    "number": {
      "id": "a7e7c447-162a-4f49-998c-add655fd6e61",
      "phone_number": "+12165455345"
    },
    "from": "+16462427059",
    "forwarded_to": {"type": "sip", "sip_endpoint": "+12165455345@kmn-comms.sip.telnyx.com"},
    "rule": "forward_all",
    "stage": "primary",
    "forwarded_by": "platform",
    "provider": "telnyx",
    "provider_call_ref": "9560e1a6-ad01-11f1-bc48-2221f7f6ad71",
    "started_at": "2026-09-11T09:24:26+00:00",
    "occurred_at": "2026-09-11T09:24:26+00:00"
  }
}

call.forwarded (fallback to the on_missed number)

The primary target did not answer within 25 s; the still-ringing caller was sent to the on_missed number. Same call_id as the primary event; primary_hangup_cause explains why the first leg ended.

{
  "id": "7f1e2d3c-4b5a-4c6d-8e9f-0a1b2c3d4e5f",
  "type": "call.forwarded",
  "created_at": "2026-09-11T09:24:52.301118",
  "payload": {
    "call_id": "4b1c9f02-3c7e-4d1a-9b0e-8a2f1c6d7e55",
    "number": {
      "id": "a7e7c447-162a-4f49-998c-add655fd6e61",
      "phone_number": "+12165455345"
    },
    "from": "+16462427059",
    "forwarded_to": {"type": "number", "phone_number": "+447912345678"},
    "rule": "on_missed",
    "stage": "fallback",
    "forwarded_by": "platform",
    "provider": "telnyx",
    "provider_call_ref": "9560e1a6-ad01-11f1-bc48-2221f7f6ad71",
    "started_at": "2026-09-11T09:24:26+00:00",
    "occurred_at": "2026-09-11T09:24:52+00:00",
    "primary_hangup_cause": "timeout"
  }
}

call.forwarded (carrier-native — reported by another provider)

The same event when the hosting carrier forwards the call itself and tells us afterwards. Only forwarded_by and provider differ — your handler needs no special case. Illustrative payload for a future carrier integration; the provider value is that carrier's slug.

{
  "id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
  "type": "call.forwarded",
  "created_at": "2026-10-02T14:03:11.508211",
  "payload": {
    "call_id": "9e8d7c6b-5a4f-4e3d-2c1b-0a9f8e7d6c5b",
    "number": {
      "id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
      "phone_number": "+14155552671"
    },
    "from": "+14155550100",
    "forwarded_to": {"type": "number", "phone_number": "+14155559876"},
    "rule": "forward_all",
    "stage": "primary",
    "forwarded_by": "carrier",
    "provider": "us_carrier",
    "provider_call_ref": "CA7f3e9c2b1d4a5e6f",
    "started_at": "2026-10-02T14:03:09+00:00",
    "occurred_at": "2026-10-02T14:03:09+00:00"
  }
}

call.completed

An answered forwarded call ended. duration_seconds counts from the answer; ended_by is caller, callee, carrier or platform.

{
  "id": "3c4d5e6f-7a8b-4c9d-0e1f-2a3b4c5d6e7f",
  "type": "call.completed",
  "created_at": "2026-09-11T09:25:25.844902",
  "payload": {
    "call_id": "4b1c9f02-3c7e-4d1a-9b0e-8a2f1c6d7e55",
    "number": {
      "id": "a7e7c447-162a-4f49-998c-add655fd6e61",
      "phone_number": "+12165455345"
    },
    "from": "+16462427059",
    "forwarded_to": {"type": "sip", "sip_endpoint": "+12165455345@kmn-comms.sip.telnyx.com"},
    "rule": "forward_all",
    "stage": "primary",
    "forwarded_by": "platform",
    "provider": "telnyx",
    "provider_call_ref": "9560e1a6-ad01-11f1-bc48-2221f7f6ad71",
    "started_at": "2026-09-11T09:24:26+00:00",
    "answered": true,
    "answered_at": "2026-09-11T09:24:35+00:00",
    "ended_at": "2026-09-11T09:25:25+00:00",
    "duration_seconds": 50,
    "hangup_cause": "normal_clearing",
    "ended_by": "callee"
  }
}

call.missed

The call was never answered. reason is one of no_answer, busy, rejected, caller_hung_up, no_forwarding_rules (the number had no rules — configure forwarding), failed.

{
  "id": "4d5e6f7a-8b9c-4d0e-1f2a-3b4c5d6e7f8a",
  "type": "call.missed",
  "created_at": "2026-09-11T09:25:00.117364",
  "payload": {
    "call_id": "4b1c9f02-3c7e-4d1a-9b0e-8a2f1c6d7e55",
    "number": {
      "id": "a7e7c447-162a-4f49-998c-add655fd6e61",
      "phone_number": "+12165455345"
    },
    "from": "+16462427059",
    "forwarded_to": {"type": "number", "phone_number": "+447912345678"},
    "rule": "on_missed",
    "stage": "fallback",
    "forwarded_by": "platform",
    "provider": "telnyx",
    "provider_call_ref": "9560e1a6-ad01-11f1-bc48-2221f7f6ad71",
    "started_at": "2026-09-11T09:24:26+00:00",
    "answered": false,
    "ended_at": "2026-09-11T09:25:00+00:00",
    "reason": "busy",
    "hangup_cause": "user_busy",
    "ended_by": "platform"
  }
}

Quick reference

Type Payload keys Action needed?
porting_order.created porting_order No — fulfill requirements at your pace
porting_order.split batch_id, porting_order_ids, reason Track all listed order ids
loa.signed document_id, signature_id, order_id, template, signer info, document_sha256 No — audit record
porting_order.status_changed porting_order, previous_status, new_status Only on rejection (fix + resubmit)
porting_order.requirement_updated porting_order_id, requirement{slug,status[,reason]} On exception: rewrite that field
porting_order.new_comment porting_order_id, comment{id,author,body} Read the note
porting_order.foc_date_changed reserved — currently never sent; FOC dates arrive as foc_actual on status_changed —
number.activated number{id,phone_number,status}, porting_order_id Configure routing if active_unconfigured
number.forwarding_updated number{id,phone_number}, forwarding{forward_all,on_missed} No — confirmation of your own change
porting_order.deleted order tombstone No
port_out.created port_out{…} No — a status_changed follows
port_out.status_changed port_out{…} (+ action / note) On action_required: approve/reject before the deadline
number.ported_out number{id,phone_number}, port_out_id Update your records — the number is gone
number.removed number{id,phone_number}, removed_by, messages_deleted Update your records — removed by platform ops
number.provider_changed number{id,phone_number}, previous_provider, provider, changed_by Informational — hosting carrier corrected by platform ops
call.forwarded call_id, number, from, forwarded_to, rule, stage, forwarded_by, provider, provider_call_ref No — a call.completed / call.missed follows
call.completed as above + answered_at, ended_at, duration_seconds, hangup_cause, ended_by No — call log / billing
call.missed as above + reason, hangup_cause, ended_by On no_forwarding_rules: configure forwarding
sms.sent message{…} No — delivery events follow
sms.delivered message{…} No
sms.failed message{…} (error set) Retry or investigate the destination
sms.received message{…} Handle the inbound text

Every event shown here is also queryable forever via the events API (GET /v2/porting/events), and every delivery attempt via the webhook audit log.