You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs-src/webhooks/events.mdx.vel
+10-16Lines changed: 10 additions & 16 deletions
Original file line number
Diff line number
Diff line change
@@ -3,17 +3,11 @@ title: Events
3
3
description: The exact wire format Spectrum sends — headers, body, and what each field contains
4
4
---
5
5
6
-
import { TypeTooltip } from "/snippets/type-tooltip.mdx";
7
-
8
-
{% set space = symbol("ts:spectrum-ts#Space") %}
9
-
{% set user = symbol("ts:spectrum-ts#User") %}
10
-
11
-
{# Note: We intentionally do NOT use TypeTooltip for `Content` or
12
-
`InboundMessage` because:
13
-
- `Content = z.infer<typeof contentSchema>` resolves to a Zod inference
14
-
reference that's unhelpful to customers.
15
-
- `InboundMessage` is generic and the extractor returns an empty signature.
16
-
The Space and User types are plain interfaces that extract cleanly. #}
6
+
{# We deliberately do NOT use TypeTooltip on the Space/User/Message types here.
7
+
The SDK interfaces include methods (`.send()`, `.edit()`, `.getMessage()`,
8
+
etc.) that don't survive `JSON.stringify` — showing them as the type of a
9
+
webhook payload field is actively misleading. The serialized shapes on the
10
+
wire are simpler: `{ id, platform }` for Space and User. #}
17
11
18
12
In the [Quickstart](/webhooks/quickstart), a real delivery flew past in `console.log`. This page is the spec — every header and every field your handler will see on every request, slowed down and labelled.
19
13
@@ -92,8 +86,8 @@ This is the only event currently emitted. It fires once per inbound message that
92
86
| Field | Type | Description |
93
87
| --- | --- | --- |
94
88
| `event` | `"messages"` | Discriminator. Always `"messages"` for this payload. |
95
-
| `space` | <TypeTooltip name="Space" type={`{{ space.signature }}`} /> | The conversation context. See [Space](#space) below. |
96
-
| `message` | object | The inbound message. See [Message](#message) below. |
89
+
| `space` | `{ id, platform }` | The conversation context. See [Space](#space) below. |
90
+
| `message` | `object` | The inbound message. See [Message](#message) below. |
97
91
98
92
#### Space
99
93
@@ -102,7 +96,7 @@ This is the only event currently emitted. It fires once per inbound message that
102
96
| `id` | `string` | Opaque, stable identifier for the conversation. Format varies by platform and space type — treat it as a string you store and pass back unchanged. For iMessage DMs, looks like `any;-;+<E.164>`; for groups, a chat GUID. |
103
97
| `platform` | `string` | The platform that owns this space. See [Providers](/spectrum-ts/providers) for the current set of values; new platforms add new values without breaking existing payloads. |
104
98
105
-
The `space.id` matches the `space.id` you'd see from the [`spectrum-ts` SDK](/spectrum-ts/spaces-and-users). To send a reply, pass it to <TypeTooltip name="Space" type={`{{ space.signature }}`} />`.send(...)` from a separately-running SDK instance — there is no public HTTP send-message endpoint today.
99
+
The `space.id` matches the `space.id` you'd see from the [`spectrum-ts` SDK](/spectrum-ts/spaces-and-users) — pass it to `Space.send(...)` from a separately-running SDK instance to reply. There is no public HTTP send-message endpoint today.
106
100
107
101
#### Message
108
102
@@ -112,8 +106,8 @@ The `space.id` matches the `space.id` you'd see from the [`spectrum-ts` SDK](/sp
112
106
| `platform` | `string` | The platform that sourced the message. Same value as `space.platform`. |
113
107
| `direction` | `"inbound"` | Always `"inbound"` — outbound messages are not delivered as webhooks. |
114
108
| `timestamp` | `string` | ISO 8601 UTC timestamp from the platform (when the user sent it). |
115
-
| `sender` | <TypeTooltip name="User" type={`{{ user.signature }}`} /> | The user who sent the message — `{ id, platform }`. The `id` format is platform-defined (e.g. for iMessage it's the E.164 phone number `+15551234567`; for WhatsApp Business it's the WA contact id). |
116
-
| `space` | <TypeTooltip name="Space" type={`{{ space.signature }}`} /> | A copy of the top-level `space` field, denormalized for convenience. |
109
+
| `sender` | `{ id, platform }` | The user who sent the message. The `id` format is platform-defined (for iMessage it's the E.164 phone number `+15551234567`; for WhatsApp Business it's the WA contact id). |
110
+
| `space` | `{ id, platform }` | A copy of the top-level `space` field, denormalized for convenience. |
117
111
| `content` | object | The message content. Shape depends on the message type — see [Content shapes](#content-shapes) below. |
Copy file name to clipboardExpand all lines: webhooks/delivery.mdx
+8-2Lines changed: 8 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,9 +5,15 @@ description: How Spectrum decides when to retry, when to give up, and what your
5
5
6
6
You know what arrives ([Events](/webhooks/events)) and how to prove it's real ([Verifying signatures](/webhooks/verifying-signatures)). This page picks up the moment *after* the worker computes a signature and starts the `POST` to your URL — what it does when your server is fast, slow, broken, or unreachable. The contract is simple but worth knowing exactly, because it determines how fault-tolerant you need to be on your end.
7
7
8
-
## The contract in one paragraph
8
+
## The contract at a glance
9
9
10
-
Spectrum tries to deliver each event for up to four attempts within a ~6.2 second window. Each attempt has a 10-second per-request timeout. Retries happen on `5xx`, `408`, `429`, network errors, and our own timeouts; other `4xx` codes mean "give up." Successful deliveries acknowledge with any `2xx`. After the budget is exhausted the event is dropped from the worker's memory — there is no durable retry queue. Customers who care about every event must dedupe and tolerate occasional misses.
10
+
-**Strong retry behaviour.** Up to 4 attempts per event, with backoff on `5xx`, `408`, `429`, network errors, and worker-side timeouts. The vast majority of deliveries land on attempt 1; the retries are there for the occasional bad minute on your side.
11
+
-**Fast acknowledgement.** Any `2xx` ends it — the worker stops as soon as your server says ok.
12
+
-**Fast permanent failure.** Other `4xx` codes (`400`/`401`/`404`/etc.) are treated as fatal — we don't waste your retry budget when the request will never succeed.
13
+
-**Bounded budget.** 10-second per-attempt timeout, ~6.2 second total across all retries. If your server is still down after that, the event is logged and the worker moves on.
14
+
-**At-least-once delivery.** A retry after your server timed out can re-deliver an event you already processed — always dedupe in your handler (see [Be idempotent](#be-idempotent) below).
15
+
16
+
This is a bounded-retry contract, not zero-loss delivery. If your use case requires *every* event regardless of downtime (financial audit, transactional state machines), pair webhooks with periodic reconciliation against the [Spectrum API](/api-reference/introduction) — covered later on this page.
Copy file name to clipboardExpand all lines: webhooks/overview.mdx
+10-20Lines changed: 10 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -40,15 +40,13 @@ The next six pages build on each other. Skim straight to the topic you need, or
40
40
5.**[Managing webhooks](/webhooks/managing-webhooks)** — operate at scale: register, list, delete, and rotate signing secrets via the API or the dashboard.
41
41
6.**[Troubleshooting](/webhooks/troubleshooting)** — common symptoms, root causes, and fixes when something goes wrong.
42
42
43
-
<Tip>
44
-
**Three ways to register and manage webhooks** — pick whichever fits how you work:
43
+
## Three ways to manage webhooks
45
44
46
-
-**Dashboard.** Open your workspace at [app.photon.codes/dashboard](https://app.photon.codes/dashboard) and use the **Webhook** tab to add, list, and remove endpoints with point-and-click. No terminal, no auth headers — friendly enough to hand to a non-engineer.
47
-
-**Interactive API reference.** Every endpoint is live in the [API reference](/api-reference/introduction) — paste your project credentials once and fire `List webhooks`, `Register webhook`, or `Delete webhook` straight from your browser. Fastest way to confirm credentials work and sanity-check a URL.
48
-
-**`curl` or any HTTP client.** The terminal flow used throughout this guide and the [Quickstart](/webhooks/quickstart). Scriptable, automatable, CI-friendly.
45
+
You can register, list, and delete webhooks through any of three surfaces — same three operations under the hood, different ergonomics:
49
46
50
-
Same three operations under the hood — just three different surfaces over them.
51
-
</Tip>
47
+
-**[Dashboard](https://app.photon.codes/dashboard).** Open your workspace and use the **Webhook** tab to add and remove endpoints with point-and-click. No terminal, no auth headers — the friendliest entry point, and fine to hand to a non-engineer.
48
+
-**[Interactive API reference](/api-reference/introduction).** Every endpoint runs straight from your browser. Paste your project credentials once and fire `List webhooks`, `Register webhook`, or `Delete webhook`. Fastest way to confirm credentials work or sanity-check a URL.
49
+
-**`curl` or any HTTP client.** The terminal flow used in the [Quickstart](/webhooks/quickstart) and the rest of this guide. Scriptable, automatable, CI-friendly.
52
50
53
51
## When to use webhooks
54
52
@@ -96,9 +94,7 @@ Four ideas cover everything else in these docs:
Today there is one event: **`messages`**. Each delivery carries `X-Spectrum-Event: messages` and a body of shape `{ event, space, message }` — see [Events](/webhooks/events) for every field.
102
98
103
99
The set will grow (reactions, typing indicators, custom provider events). New event types are additive: existing handlers that ignore unknown values keep working without changes.
104
100
@@ -113,16 +109,10 @@ Your signing secret is returned exactly once, in the response of `POST /webhooks
Copy file name to clipboardExpand all lines: webhooks/verifying-signatures.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
---
2
2
title: Verifying signatures
3
-
description: Confirm each delivery is genuine, unmodified, and recent — copy-paste verifier code for Node, Bun, and Python
3
+
description: Confirm each delivery is genuine, unmodified, and recent — copy-paste verifier code for Node, Bun, Python, and Go
4
4
---
5
5
6
6
You saw the verifier as a copy-paste in the [Quickstart](/webhooks/quickstart), and you saw the `X-Spectrum-Signature` header itself in [Events](/webhooks/events). This page is the *why* — what each line of that verifier is doing and how to port it to a different stack.
0 commit comments