Documentation

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:

  1. The database write happens before the response, not after it. calls/end commits the interaction row inside the same request — if that write fails, the request itself fails instead of acknowledging a call that was never recorded.
  2. 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/end responds.
  3. 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 204 response 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