@curviate/sdk 0.19.0 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -121,7 +121,9 @@ try {
121
121
  }
122
122
  ```
123
123
 
124
- All 34 error codes are documented in the [API reference](https://docs.curviate.com).
124
+ Every error code is documented in the [API reference](https://docs.curviate.com). The
125
+ exported `ErrorCode` type is the complete set, so `tsc` tells you when a `switch` over
126
+ `err.code` has missed one.
125
127
 
126
128
  ---
127
129
 
@@ -178,7 +180,7 @@ app.post("/webhook", express.raw({ type: "application/json" }), async (req, res)
178
180
  case "account.connected":
179
181
  handleAccountConnected(event.data);
180
182
  break;
181
- // 22 more event types, all in the CurviateEvent union.
183
+ // Every other event type is a case in the CurviateEvent union.
182
184
  }
183
185
 
184
186
  res.sendStatus(200);
@@ -194,8 +196,26 @@ app.post("/webhook", async (c) => {
194
196
 
195
197
  `constructEvent` always returns a `Promise<CurviateEvent>`. Always `await` it.
196
198
 
197
- Each event also carries its delivery metadata: `event.id` (a `wdl_` delivery id you
198
- can de-duplicate retries on), `event.webhook_id`, and `event.delivered_at`.
199
+ Each event also carries its delivery metadata: `event.id`, `event.webhook_id`, and
200
+ `event.delivered_at`.
201
+
202
+ ### De-duplicating retries
203
+
204
+ Delivery is at-least-once, so your handler can see the same logical event more than
205
+ once. The key that survives a retry is the payload composite `event.event` plus
206
+ `event.data.account_id` plus `event.data.occurred_at`, which the platform re-sends
207
+ byte-identical on every attempt:
208
+
209
+ ```ts
210
+ const key = `${event.event}:${event.data.account_id}:${event.data.occurred_at}`;
211
+ if (await alreadyProcessed(key)) return res.sendStatus(200);
212
+ ```
213
+
214
+ **Do not key on `event.id`.** That is a `wdl_` id minted per delivery *attempt*, so a
215
+ retry arrives with a different one and storing it would record the same event twice,
216
+ missing exactly the duplicates you were guarding against. It is still worth logging:
217
+ `event.id` is how you match one attempt to one line in your delivery logs, keyed
218
+ alongside the stable `occurred_at` composite above.
199
219
 
200
220
  `WebhookSignatureError` is NOT a `CurviateError`. Narrow with `instanceof WebhookSignatureError`.
201
221
  Its `reason` tells you where to look: `malformed_header` means the signature header could not be