Whim voice note webhook API
Webhook contract v1 is the reference for receiving voice notes from Whim on iPhone and Apple Watch.
Whim sends one multipart/form-data POST per Attempt to the configured endpoint. Parts are metadata (application/json, exact UTF-8 bytes) and audio (audio/mp4, an AAC .m4a file). The configured endpoint receives the audio, title, capture timestamp/duration, source device kind, workflow ID, app version/build, and Note/Attempt IDs. Whim does not have a hosted relay.
The JSON has schema_version: 1, event: "note.created", note_id, attempt_id, created_at (UTC ISO-8601), duration_ms, source (iphone or apple_watch), title, title_source (transcription, timestamp, or recovered), capture_outcome (completed, interrupted, or recovered), workflow_id, audio: { sha256, size_bytes }, and app: { version, build }.
Metadata example
The strings below illustrate the schema; UUIDs, timestamps, and hashes are replaced with real values in each request.
{
"schema_version": 1,
"event": "note.created",
"note_id": "immutable UUID",
"attempt_id": "UUID",
"created_at": "ISO-8601 UTC timestamp",
"duration_ms": 42000,
"source": "iphone",
"title": "Idea for the onboarding flow",
"title_source": "transcription",
"capture_outcome": "completed",
"workflow_id": "default",
"audio": {
"sha256": "lowercase hexadecimal digest",
"size_bytes": 338112
},
"app": {
"version": "1.0.0",
"build": "1"
}
}
Authentication and integrity
Each request carries these headers:
| Header | Value |
|---|---|
X-Whim-Note-ID |
Immutable Note UUID; the idempotency key |
X-Whim-Attempt-ID |
UUID identifying this transport Attempt |
X-Whim-Timestamp |
Unix seconds at request creation |
X-Whim-Metadata-SHA256 |
Lowercase hex SHA-256 of the exact metadata bytes |
X-Whim-Audio-SHA256 |
Lowercase hex SHA-256 of the exact audio bytes |
Authorization |
Bearer <token> when configured |
X-Whim-Signature |
v1=<lowercase hex HMAC-SHA256> when configured |
Compute HMAC with the configured secret over this UTF-8 text, with newline separators and no trailing newline:
v1
<timestamp>
<note_id>
<attempt_id>
<metadata_sha256>
<audio_sha256>
Verify the raw part hashes before using their content. Do not reserialize JSON to compute the metadata digest. Compare signatures in constant time. The reference receiver allows five minutes of clock skew for signed requests; keep server/device clocks accurate.
Idempotency and responses
The iPhone and Watch may concurrently deliver the same Note with different Attempt IDs, titles, or Configuration Revisions. A lost response can also produce a later retry. Atomically store or enqueue one logical work item keyed by Note ID. A duplicate valid request should return success and the original Note ID without creating downstream work again. Keep the first accepted payload; Attempt IDs are not deduplication keys.
Any 2xx response creates a Receipt in Whim. Echo the ID in X-Whim-Note-ID and preferably JSON:
{ "note_id": "the-note-uuid", "duplicate": false }
The same acknowledgement with duplicate: true is returned for a duplicate. Network failures, 408, 425, 429, and 5xx are retryable; other 4xx fail immediately. Redirects are rejected. Automatic retries stop after three actual failures, with earliest retry delays of one minute and fifteen minutes; 429 Retry-After can defer eligibility. OS background scheduling may delay an eligible Attempt further.
event: "configuration.test" uses the same body/signature contract with a fresh Note and Attempt ID. Validate it and echo its Note ID, but do not enqueue it as a user Note. Missing ID acknowledgement produces a setup warning in Whim even when the HTTP response succeeds.
Connect your endpoint
See the webhook setup guide for configuring Whim, testing delivery, and troubleshooting common errors. Your own receiver controls storage, processing, and backups; Whim does not operate it.