POST /v1/calls/end returns 204 No Content on an accepted request. That proves the interaction is already committed durably — the database write happens before the response returns, so the next immediate recall for that caller does contain it. It does not prove that every other downstream job (enrichment, a background bridge) has completed, or that a client should parse JSON.
Acknowledgement and observation are different receipts
For Northsun's caller-memory path, the two moments are the same request: the database write always completes durably before calls/end responds 204, and a bounded, best-effort write-through attempts to keep the cache the next recall reads from in sync within that same request. That is not true of every asynchronous system, and it is not true of every downstream step behind this response — enrichment and the retry-net queue publish stay genuinely asynchronous.
The quickstart therefore still asks for a later recall with a new session ID, to prove the guarantee against your own integration rather than trust the claim. The unique synthetic observation should appear in memory.summary or memory.recent_calls immediately, with no processing interval to wait through. See Hangup, and what happens next for the full guarantee.
Do not parse a body
This is wrong:
const response = await fetch(url, options);
const receipt = await response.json();
A 204 has no response body. Branch on status and preserve correlation data instead:
const response = await fetch(url, options);
if (response.status !== 204) {
throw await toNorthsunError(response);
}
return {
acknowledgedAt: new Date().toISOString(),
sessionId: redactedSessionId,
};
That local receipt reflects only what your client observed synchronously. The interaction itself is already committed durably by the time 204 returns — label the receipt "acknowledged," and treat a later read as verification of your own integration, not of the API's guarantee.
Retrying an uncertain write
Voice platforms retry webhooks, networks fail after sending bytes, and clients can lose the response after the server handled the request. Use the platform’s stable call ID to deduplicate in your application. Avoid blindly posting the same completed call in an unbounded loop.
When the result is uncertain:
- retain the UTC time, redacted call/session ID, endpoint, and request/trace headers;
- inspect a later read before creating another write;
- retry only under a bounded policy appropriate to your idempotency design;
- escalate with the minimal safe diagnostic receipt if state remains ambiguous.
The proof ladder
Name exactly which rung you reached:
- Request serialized locally.
- Server returned
204. - A later recall exposed the controlled interaction.
- The exact voice-platform webhook path produced the same result.
- The behavior survived duplicate delivery, missing enrichment, and a temporary failure.
Only the final rungs support a production lifecycle claim for that configuration.
Run the Quickstart, inspect API reference, and use Troubleshooting when the acknowledgement and later read disagree.