From recording to Clip or Memo
A recording is the common audio input. The app processes it into a Clip or a Memo, using the selected input mapping:
Text syncs to the cloud for both. The API does not store audio. Duration is an
intended use, not an automatic classification rule. Recording is the shared
resource name and the database table remains
recordings. Each row has the
result type clip or memo; Memo is not renamed to Recording.
The recording object
Create, read, and edit responses use the samerecording object:
type is clip or memo. A device capture can include deviceId.
An import can include an optional externalId from your own system.
Timestamps are Unix milliseconds.
status tells you whether text is pending, transcribing, ready,
no_speech, or failed. The app reports transcription progress. Saving
nonempty transcript text makes the recording ready; this API does not start
transcription. A pending app capture cannot be edited until the app saves it.
Create and retry
POST /recordings accepts type plus optional title, transcript, summary,
recordedAt, externalId, and audio. Include Idempotency-Key on every create.
Retry with the same key and body to recover the saved result without duplicate
items or overwritten edits. A conflicting body returns 409; retrying a deleted
recording returns 410.
If you provide externalId, repeated imports of that ID with the same body also
reuse the existing recording. Retry keys and external IDs are scoped to the
integration associated with your key. A newly created key has a new integration
identity; keep the original key for retries of earlier imports.
A key with create or edit permission but no read permission receives only
{ "recording": { "id": "…", "revision": 1 } }. It cannot retrieve text later
added by the account owner.
Edit and delete
ReadGET /recordings/{id} and copy its ETag response header into If-Match.
Then send only the fields you want to change:
title, transcript, summary, and pinned.
A recording’s type and capture identity stay fixed. DELETE /recordings/{id}
also requires If-Match. A newer edit returns 412; read again and reconcile
before retrying. A missing If-Match returns 428.
Search
GET /recordings accepts type, q, deviceId, status, from, and to.
Search matches title and transcript. Date bounds are inclusive. Results are
newest first by capture time. Set limit up to 100 and pass nextCursor as
cursor to continue with the same filters; null means the last page.
For the latest clip, use GET /recordings?type=clip&limit=1. Check its status:
it may still be processing. Pagination reflects current data, not a frozen snapshot.
Local audio
Fortype: "memo", creation may include local file references:
audio: [] and cannot be created with audio references.
Audio used during capture and transcription is an in-progress recording input,
not retained Clip audio. Once converted and saved as a Clip, only text remains.
A pending or failed input is not a completed Clip. Client transfer and cleanup
reports remain part of the app protocol.
Errors
Errors containerror.code and error.message. The X-Request-Id header identifies
a request for support. JSON requests are limited to 1,500,000 bytes.