Capture Webhook
The capture webhook turns a voice note or a piece of text into an Inbox task. Any device, app, or script that can send an HTTP request posts the text, and optionally an audio recording, to your own cloud server. The server creates the task, attaches the audio, and your devices pick both up on the next sync.
This needs the self-hosted cloud server. If you run Mindwtr without a server, capture from the phone share sheet or Siri instead.
The endpoint
POST /v1/captureEvery request carries the same bearer token as the rest of the API, in an Authorization: Bearer <token> header. The body can be multipart/form-data, application/json with the same field names, or text/plain, where the whole body is the transcription. Only multipart/form-data can carry audio: JSON and plain-text requests are text only, and an audio field inside JSON is ignored. Unknown fields are ignored.
Text only
curl -X POST https://your-server.example/v1/capture \
-H "Authorization: Bearer $MINDWTR_TOKEN" \
-H "Content-Type: text/plain" \
--data "Call the dentist about the crown"Audio with a transcription
curl -X POST https://your-server.example/v1/capture \
-H "Authorization: Bearer $MINDWTR_TOKEN" \
-F "transcription=Call the dentist about the crown" \
-F "audio=@note.m4a" \
-F "recordedAt=1756900000000" \
-F "client=Pebble Index 01"Fields
| Field | What it does |
|---|---|
transcription | The captured text. The first line becomes the task title, and the full text becomes the description. text and title are accepted as other names for the same field. |
audio | The recording to attach to the task. It syncs to your devices like any other attachment. It is only read from a multipart/form-data request. |
recordedAt | When the capture happened, as epoch milliseconds or an ISO 8601 timestamp. It becomes the task's creation time when it is valid and not in the future. |
client | A short label for the device or app that sent the capture. It is accepted and ignored, so senders such as the Pebble app keep working. |
captureId | Optional. A UUID the sender chooses for this capture; it becomes the new task's id. Send the same value again on a retry and the server answers 200 with "replayed": true and adds nothing. A malformed value is rejected with 400. |
Send at least one of transcription and audio. The recording can be m4a, mp4, aac, mp3, wav, ogg, or webm.
Responses
| Status | Meaning |
|---|---|
201 | The task was created. The response body is the new task. |
400 | Neither a transcription nor an audio file was sent. |
401 | The token is missing or wrong. |
413 | The request is over the server's size limit: an audio upload above the attachment limit, or a transcription above the text limit. |
415 | The audio file type is not supported. |
Capture-only token
A device that only captures should not hold a token that can read, change and delete everything in your account. A capture-only token is a second secret for the same account. The server accepts it on POST /v1/capture and nowhere else.
Create one with your full token. The label is optional. The response shows the token once. The server never stores it in clear, so copy it now.
curl -X POST https://your-server.example/v1/capture-tokens \
-H "Authorization: Bearer $MINDWTR_TOKEN" \
-H "Content-Type: application/json" \
--data '{"label":"Pebble ring"}'{
"id": "6f1c2d1e-8a4b-4c3e-9f2a-1b2c3d4e5f60",
"token": "mwc_…",
"label": "Pebble ring",
"createdAt": "2026-09-06T10:12:00.000Z"
}List the tokens on the account. The response has id, label and createdAt for each token, and no secrets.
curl https://your-server.example/v1/capture-tokens \
-H "Authorization: Bearer $MINDWTR_TOKEN"Revoke one by its id.
curl -X DELETE https://your-server.example/v1/capture-tokens/<id> \
-H "Authorization: Bearer $MINDWTR_TOKEN"- A capture-only token works only on
POST /v1/capture. There it behaves exactly like the full token: same body formats, same responses, same rate limit as the account. Every other route answers403. - An account can hold up to 20 capture-only tokens.
- In allowlist mode, a capture-only token stops working when the account's full token is removed from the allowlist.
Pebble Index 01
The Pebble Index 01 app sends voice notes in exactly this format, and it lets you add your own request headers. So there is no glue code: you only fill in two settings.
- Open the Pebble app on your phone and go to the webhook settings for voice notes
- Set the webhook URL to
https://your-server.example/v1/capture, with your own server address in place of the example - Add a request header named
Authorizationwith the valueBearer <token>, using a capture-only token from the section above. Your full token also works, but the capture-only token is the safer choice for a device that only records notes - Record a note on the watch. It reaches your Inbox on the next sync, with the transcription as the task and the recording attached
Other devices and automations
Nothing here is Pebble-specific. Anything that can make an HTTP POST works the same way:
- iOS and Apple Watch Shortcuts: a Get contents of URL action, method POST, with the header and a text field. See the Capture from Apple Watch recipe on the Apple Shortcuts page
- Android automation apps such as Tasker: an HTTP Request action with the same URL and header
- Home Assistant: a
rest_commandthat posts the text of an automation or a voice assistant result - Shell scripts and cron jobs: the curl commands above, with the token in an environment variable