Hangup, and what happens next
Submit what happened after the call ends:
curl -i -sS -X POST https://mcp.mnemix.ai/v1/calls/end \
-H "Authorization: Bearer $MNEMIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+15551234567",
"session_id": "call_demo_01",
"transcript": [
{ "role": "user", "text": "Please call me Tuesday morning.", "ts_ms": 0 },
{ "role": "agent", "text": "I will record that callback request.", "ts_ms": 2400 }
],
"duration_s": 18,
"outcome": "callback_requested"
}'
A successful request returns 204 No Content. Call it once after hangup, using the same phone_number and session_id you used on recall.
The next recall sees this call
The next recall_and_enrich for this caller sees this call. Immediately — not "within five seconds," not "eventually."
That guarantee shipped as a same-day fix and it is precise about what it covers, so it is worth stating exactly what happens inside the request, in order:
- The database write happens before the response, not after it.
calls/endcommits the interaction row inside the same request — if that write fails, the request itself fails instead of acknowledging a call that was never recorded. - The cache the next recall reads from is updated synchronously, in the same request — a bounded write-through, not a background job. Each Redis command inside it carries its own strict fuse and its own single retry, not one retry for the write-through as a whole. If a cached entry already exists for that caller, this call is merged into it — history and call count both — before
calls/endresponds. - The write-through is timestamped to survive a race with an in-flight recall. If a recall for the same caller was already reading the database when this call ended, a timestamp comparison on the cache write keeps the hangup's data from being silently overwritten by that recall's slightly-older read landing later. The more recent event wins by construction, not by hoping the writes land in order.
The practical result: call recall_and_enrich again right after hangup and the history is already there. You do not need a poll loop, a fixed delay, or a "wait a few seconds and try again" retry policy to see this specific call. (Enrichment — Trestle person and company lookups plus Twilio Lookup phone lookups — is a separate, genuinely asynchronous pipeline; see What recall gives you back for how that stays independently nullable.)
What the queue does now
calls/end also publishes a job to a durable queue. Before this fix, that queue was the write mechanism — if the publish failed silently, the call was acknowledged but never recorded. It no longer is. The database write in step 1 above is what makes the call durable; the queued job is a retry net: a belt-and-suspenders reprocessing path for cases the synchronous write already handled, made idempotent against it (a duplicate run of the same call is a no-op, not a second row). If your platform's webhook delivery is unreliable and retries deliveries, deduplicate by your own call identifier before calling calls/end again — see Errors, rate limits, and retries.
What this does not promise
- It does not promise that enrichment (person/company/phone lookups) is complete by the next recall — that pipeline is separately asynchronous by design.
- It does not change the
204response itself — there is still no body, and the status code is an acknowledgement of a successfully durable write, not a receipt for a separate downstream process you need to poll. - It applies to the caller-memory path documented here. It is not a latency benchmark and does not change the public latency language, which stays
designed for sub-300ms voice recall.
Next steps
- What recall gives you back — the full shape of the recall you'll get back afterward.
- Production readiness — prove this lifecycle end-to-end before you launch.
- Troubleshooting — what to check if a later recall still doesn't show the call.