{"openapi":"3.1.0","info":{"title":"Monologue Public API","description":"Read your notes with a personal API token, and receive webhook events when notes finish processing. All API endpoints in this reference require the `notes:read` scope; the Webhooks section documents the events Monologue delivers to your endpoint and how to verify them.","version":"0.1.0"},"paths":{"/v1/public-api/notes":{"get":{"tags":["Notes"],"summary":"List notes","description":"Returns the authenticated user's notes. Authenticate with a personal API token that includes the `notes:read` scope.","operationId":"listNotes","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Maximum number of notes to return per page.","default":20,"title":"Limit"},"description":"Maximum number of notes to return per page."},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque pagination cursor returned by a previous list response.","title":"Cursor"},"description":"Opaque pagination cursor returned by a previous list response."},{"name":"created_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only return notes created after this ISO 8601 timestamp.","title":"Created After"},"description":"Only return notes created after this ISO 8601 timestamp."},{"name":"created_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only return notes created before this ISO 8601 timestamp.","title":"Created Before"},"description":"Only return notes created before this ISO 8601 timestamp."},{"name":"updated_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only return notes updated after this ISO 8601 timestamp.","title":"Updated After"},"description":"Only return notes updated after this ISO 8601 timestamp."},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search note titles, summaries, and transcripts.","title":"Q"},"description":"Search note titles, summaries, and transcripts."},{"name":"tag_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string","format":"uuid"}},{"type":"null"}],"description":"Only return notes assigned to any supplied tag ID. Repeat this parameter to filter by multiple tags.","title":"Tag Id"},"description":"Only return notes assigned to any supplied tag ID. Repeat this parameter to filter by multiple tags."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicNoteListResponse"}}}},"400":{"description":"The request included an invalid filter or cursor."},"401":{"description":"Missing or invalid personal API token."},"403":{"description":"The personal API token is missing the required scope."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/public-api/notes/{note_id}":{"get":{"tags":["Notes"],"summary":"Get a note","description":"Returns the full details for a single note that belongs to the authenticated user.","operationId":"getNote","security":[{"HTTPBearer":[]}],"parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Note Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicNoteResponse"}}}},"401":{"description":"Missing or invalid personal API token."},"403":{"description":"The personal API token is missing the required scope."},"404":{"description":"The note was not found for the authenticated user."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"NoteTagResponse":{"properties":{"tag_id":{"type":"string","title":"Tag Id"},"name":{"type":"string","title":"Name"},"position":{"type":"integer","title":"Position"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"source":{"type":"string","enum":["user","auto"],"title":"Source"},"confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Confidence"}},"type":"object","required":["tag_id","name","position","created_at","updated_at","source"],"title":"NoteTagResponse"},"PublicNoteListItemResponse":{"properties":{"note_id":{"type":"string","title":"Note Id","description":"Unique identifier for the note."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Generated or user-facing note title."},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary","description":"Short summary of the note contents."},"tags":{"items":{"$ref":"#/components/schemas/NoteTagResponse"},"type":"array","title":"Tags","description":"Tags assigned to the note, including auto-tag metadata."},"recorded_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Recorded At","description":"Timestamp when recording began, when supplied by the client."},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Timestamp when the backend created the note."},"updated_at":{"type":"string","format":"date-time","title":"Updated At","description":"Timestamp when the note was last updated."}},"type":"object","required":["note_id","created_at","updated_at"],"title":"PublicNoteListItemResponse"},"PublicNoteListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/PublicNoteListItemResponse"},"type":"array","title":"Items","description":"Notes for the current page."},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Pagination cursor for the next page, if more results exist."}},"type":"object","required":["items"],"title":"PublicNoteListResponse"},"PublicNoteResponse":{"properties":{"note_id":{"type":"string","title":"Note Id","description":"Unique identifier for the note."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Generated or user-facing note title."},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary","description":"Short summary of the note contents."},"transcript":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transcript","description":"Full transcript text for the note."},"transcript_segments":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Transcript Segments","description":"Structured transcript segments, when available."},"tags":{"items":{"$ref":"#/components/schemas/NoteTagResponse"},"type":"array","title":"Tags","description":"Tags assigned to the note, including auto-tag metadata."},"recorded_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Recorded At","description":"Timestamp when recording began, when supplied by the client."},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Timestamp when the backend created the note."},"updated_at":{"type":"string","format":"date-time","title":"Updated At","description":"Timestamp when the note was last updated."}},"type":"object","required":["note_id","created_at","updated_at"],"title":"PublicNoteResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WebhookTranscriptSegment":{"type":"object","title":"WebhookTranscriptSegment","description":"One diarized transcript segment. For notes without diarization data (legacy notes or single-channel edge cases) the transcript is a single segment holding the full text with `speaker`, `start`, and `end` all `null` - the shape stays uniform so you only write one parser.","required":["speaker","start","end","text"],"properties":{"speaker":{"type":["string","null"],"description":"Speaker label (e.g. `speaker_0`), or `null` when no diarization data exists.","examples":["speaker_0"]},"start":{"type":["number","null"],"description":"Segment start offset in seconds, or `null`.","examples":[0]},"end":{"type":["number","null"],"description":"Segment end offset in seconds, or `null`.","examples":[3.2]},"text":{"type":["string","null"],"description":"Transcribed text for this segment.","examples":["This is a sample transcript segment."]}}},"WebhookNoteProcessedData":{"type":"object","title":"WebhookNoteProcessedData","required":["note_id","status","title","summary","transcript","duration_seconds","created_at","updated_at","api_url"],"properties":{"note_id":{"type":"string","description":"Unique identifier for the note.","examples":["8f14e45f-ceea-467f-a34e-4a3d1e1a89b2"]},"status":{"type":"string","description":"Note status; `\"completed\"` for this event.","examples":["completed"]},"title":{"type":["string","null"],"description":"Generated or user-facing note title."},"summary":{"type":["string","null"],"description":"Short summary of the note contents."},"transcript":{"type":"array","description":"Transcript as an array of segments. Always at least one segment; see `WebhookTranscriptSegment` for the no-diarization fallback shape.","items":{"$ref":"#/components/schemas/WebhookTranscriptSegment"}},"duration_seconds":{"type":["integer","null"],"description":"Audio duration in seconds, when known.","examples":[6]},"created_at":{"type":["string","null"],"format":"date-time","description":"When the note was created (RFC 3339, UTC)."},"updated_at":{"type":["string","null"],"format":"date-time","description":"When the note was last updated (RFC 3339, UTC)."},"api_url":{"type":"string","description":"URL of this note in the notes API - fetch it with your personal API token for the note's current state.","examples":["https://api.monologue.to/v1/public-api/notes/8f14e45f-ceea-467f-a34e-4a3d1e1a89b2"]}}},"WebhookNoteFailedData":{"type":"object","title":"WebhookNoteFailedData","required":["note_id","status","error_message","created_at","updated_at","api_url"],"properties":{"note_id":{"type":"string","description":"Unique identifier for the note."},"status":{"type":"string","description":"Note status; `\"failed\"` for this event.","examples":["failed"]},"error_message":{"type":["string","null"],"description":"Human-readable reason the note failed.","examples":["Transcription failed: audio file was empty"]},"created_at":{"type":["string","null"],"format":"date-time","description":"When the note was created (RFC 3339, UTC)."},"updated_at":{"type":["string","null"],"format":"date-time","description":"When the note was last updated (RFC 3339, UTC)."},"api_url":{"type":"string","description":"URL of this note in the notes API."}}},"WebhookPingData":{"type":"object","title":"WebhookPingData","required":["message"],"properties":{"message":{"type":"string","examples":["Monologue webhook ping. Your endpoint is wired up."]}}},"WebhookNoteProcessedEvent":{"type":"object","title":"WebhookNoteProcessedEvent","required":["type","timestamp","data"],"properties":{"type":{"type":"string","const":"note.processed"},"timestamp":{"type":"string","format":"date-time","description":"When this delivery attempt was serialized (RFC 3339, UTC). Retries re-serialize, so retried deliveries carry a newer timestamp and the note's current state."},"data":{"$ref":"#/components/schemas/WebhookNoteProcessedData"}}},"WebhookNoteFailedEvent":{"type":"object","title":"WebhookNoteFailedEvent","required":["type","timestamp","data"],"properties":{"type":{"type":"string","const":"note.failed"},"timestamp":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/WebhookNoteFailedData"}}},"WebhookPingEvent":{"type":"object","title":"WebhookPingEvent","required":["type","timestamp","data"],"properties":{"type":{"type":"string","const":"ping"},"timestamp":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/WebhookPingData"}}}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer","description":"Personal API token created in Monologue Settings. Every public API request requires the `notes:read` scope.","x-scopes":{"notes:read":"Read the authenticated user's notes."}}}},"tags":[{"name":"Notes","description":"Read the authenticated user's notes with a personal API token."},{"name":"Webhooks","description":"Monologue can notify your server the moment a note finishes processing, so you can pipe transcripts into your own tools without polling.\n\n## Events\n\n| Event | When it is sent |\n| --- | --- |\n| `note.processed` | A note finished processing successfully. The payload carries the transcript, summary, and metadata. |\n| `note.failed` | A note could not be processed. The payload carries the error message. |\n| `ping` | A one-off connectivity check, sent automatically when you create an endpoint. |\n\nEvery delivery is an HTTPS `POST` with a JSON envelope: `type`, `timestamp` (when this delivery attempt was serialized, RFC 3339 UTC), and the event-specific `data`. The exact schemas are documented below in this section.\n\n## Creating an endpoint\n\nCreate and manage webhook endpoints from **Settings** in the Monologue apps (macOS, iOS, or web). Endpoint URLs must be public `https://` URLs - plain `http://`, `localhost`, and private/internal addresses are rejected. When you create an endpoint you get its signing secret (`whsec_...`) and Monologue immediately sends a `ping` event so you can confirm the wiring end to end.\n\n## Verify signatures - do not skip this\n\nThe URL of your endpoint is not a secret you can rely on: anyone who discovers it can POST forged JSON that looks exactly like a Monologue event. Every delivery is therefore signed, and verifying that signature proves all three things you need: the event came from Monologue (**origin**), the body was not modified in transit (**integrity**), and it is not an old delivery being replayed (**freshness**).\n\nMonologue signs deliveries per the [Standard Webhooks](https://www.standardwebhooks.com) specification. Each request carries:\n\n| Header | Meaning |\n| --- | --- |\n| `webhook-id` | Unique message id (`msg_...`). Stable across retries of the same event - use it to deduplicate. |\n| `webhook-timestamp` | Unix timestamp (seconds) of this delivery attempt. |\n| `webhook-signature` | One or more space-delimited signatures, e.g. `v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=`. |\n\nThe signed content is `{webhook-id}.{webhook-timestamp}.{raw request body}` and the signature is `v1,` followed by the base64 HMAC-SHA256 of that string under your endpoint's `whsec_` secret.\n\n**Do not hand-roll the verification.** Use the official [`standardwebhooks`](https://github.com/standard-webhooks/standard-webhooks) library - it strips the `whsec_` prefix, compares in constant time, enforces a 5-minute timestamp tolerance, and accepts any one of multiple signatures.\n\nPython (FastAPI):\n\n```python\nfrom fastapi import FastAPI, Request, Response\nfrom standardwebhooks import Webhook, WebhookVerificationError\n\napp = FastAPI()\nwh = Webhook(\"whsec_...\")  # your endpoint's signing secret\n\n@app.post(\"/webhooks/monologue\")\nasync def monologue_webhook(request: Request) -> Response:\n    body = await request.body()  # raw bytes - verify before parsing\n    try:\n        event = wh.verify(body, dict(request.headers))\n    except WebhookVerificationError:\n        return Response(status_code=401)\n\n    # Acknowledge fast; do heavy work asynchronously.\n    if event[\"type\"] == \"note.processed\":\n        ...  # enqueue processing of event[\"data\"]\n    return Response(status_code=204)\n```\n\nJavaScript / TypeScript (Express):\n\n```typescript\nimport express from \"express\";\nimport { Webhook, WebhookVerificationError } from \"standardwebhooks\";\n\nconst app = express();\nconst wh = new Webhook(process.env.MONOLOGUE_WEBHOOK_SECRET!); // \"whsec_...\"\n\n// The signature covers the raw body: use express.raw, NOT express.json.\napp.post(\n  \"/webhooks/monologue\",\n  express.raw({ type: \"application/json\" }),\n  (req, res) => {\n    let event;\n    try {\n      event = wh.verify(req.body, req.headers as Record<string, string>);\n    } catch (err) {\n      res.status(401).end();\n      return;\n    }\n\n    res.status(204).end(); // acknowledge fast; process asynchronously\n    if (event.type === \"note.processed\") {\n      // handle event.data\n    }\n  },\n);\n```\n\nAlways verify against the **raw request body** exactly as received - if your framework parses and re-serializes the JSON first, the bytes (key order, whitespace) can change and verification will fail.\n\n### Secret rotation\n\nYou can rotate an endpoint's secret from Settings at any time. The previous secret stays valid for 24 hours, and during that overlap `webhook-signature` contains multiple space-delimited signatures (one per active secret). The `standardwebhooks` library accepts the delivery if any of them matches, so rotation needs no special handling on your side.\n\n## Delivery semantics\n\n- **At-least-once.** The same event can occasionally be delivered more than once. Deduplicate on `webhook-id`, which is stable across retries.\n- **No ordering guarantees.** Events may arrive out of order. Use the envelope `timestamp` to sequence, and treat `GET {data.api_url}` (the notes API, same personal API token) as the source of truth. Payloads are serialized at send time, so a retried delivery carries the note's *current* state, not a stale snapshot.\n- **Respond quickly with a 2xx.** Each attempt times out after 20 seconds. Acknowledge first, then do heavy work asynchronously; a timeout counts as a failed attempt.\n- **Retries (automatic events only).** When a `note.processed` or `note.failed` delivery gets a non-2xx response or times out, Monologue retries up to 8 attempts over ~28 hours: immediately, then after 5 seconds, 5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours, and 10 hours. Manual sends - the `ping` on endpoint creation, **Send test event**, and redeliveries - are attempted exactly once and never retried; if one fails, just trigger it again from Settings.\n- **Redirects are not followed.** A 3xx response counts as a failed attempt - point Monologue directly at the final URL.\n- **410 Gone disables the endpoint immediately.** Respond `410` if you want Monologue to stop sending to an endpoint.\n- **Failure escalation.** If an endpoint keeps failing automatic deliveries, you get a warning email after 24 hours; after 72 hours of continuous failures the endpoint is disabled automatically and you get a second email with a one-click re-enable. Failed manual sends never start a failure streak (a successful one does clear it). Events that occur while an endpoint is disabled are not replayed - catch up via the notes API.\n\n## Testing locally\n\n- Paste a [webhook.site](https://webhook.site) URL into Settings as a temporary endpoint to watch raw deliveries arrive, including the `webhook-id`, `webhook-timestamp`, and `webhook-signature` headers.\n- To test verification for real, expose a local server with [ngrok](https://ngrok.com) (`ngrok http 3000`), register the `https://` forwarding URL, and run one of the snippets above. Use **Send test event** in Settings to trigger a sample `note.processed` delivery on demand.\n"}],"webhooks":{"note.processed":{"post":{"tags":["Webhooks"],"summary":"Note processed","description":"Sent when a note finishes processing successfully. The payload contains the full transcript (as diarized segments), summary, and metadata. Verify the signature before trusting the payload; for the note's current state, fetch `data.api_url` with your personal API token.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"},"description":"Unique message id (`msg_...`), stable across retries of the same event. Deduplicate on this value.","example":"msg_2f9a4b6c-7d1e-4c3a-9b0f-5e6d7c8b9a01"},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Unix timestamp (seconds) of this delivery attempt.","example":"1767139200"},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"},"description":"Standard Webhooks signature(s): `v1,` + base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}` under your `whsec_` secret. May contain multiple space-delimited signatures during the 24-hour secret-rotation overlap; accept if any matches.","example":"v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="},{"name":"user-agent","in":"header","required":true,"schema":{"type":"string","const":"Monologue-Webhooks/1.0"},"description":"Always `Monologue-Webhooks/1.0`."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookNoteProcessedEvent"},"example":{"type":"note.processed","timestamp":"2026-07-07T12:00:03.214823Z","data":{"note_id":"8f14e45f-ceea-467f-a34e-4a3d1e1a89b2","status":"completed","title":"Standup notes","summary":"Daily standup covering the webhooks launch.","transcript":[{"speaker":"speaker_0","start":0,"end":3.2,"text":"Yesterday I shipped webhook deliveries."},{"speaker":"speaker_1","start":3.6,"end":6.1,"text":"Today I am writing the documentation."}],"duration_seconds":6,"created_at":"2026-07-07T11:59:41Z","updated_at":"2026-07-07T12:00:03Z","api_url":"https://api.monologue.to/v1/public-api/notes/8f14e45f-ceea-467f-a34e-4a3d1e1a89b2"}}}}},"responses":{"2XX":{"description":"Return any 2xx status within 20 seconds to acknowledge the delivery. For automatic `note.processed` / `note.failed` deliveries, any other status (3xx included - redirects are not followed) or a timeout triggers the retry schedule; manual sends (the creation `ping`, test events, redeliveries) are attempted exactly once. `410 Gone` disables the endpoint immediately in either case."}}}},"note.failed":{"post":{"tags":["Webhooks"],"summary":"Note failed","description":"Sent when a note could not be processed. `data.error_message` explains why. Verify the signature before trusting the payload.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"},"description":"Unique message id (`msg_...`), stable across retries of the same event. Deduplicate on this value.","example":"msg_2f9a4b6c-7d1e-4c3a-9b0f-5e6d7c8b9a01"},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Unix timestamp (seconds) of this delivery attempt.","example":"1767139200"},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"},"description":"Standard Webhooks signature(s): `v1,` + base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}` under your `whsec_` secret. May contain multiple space-delimited signatures during the 24-hour secret-rotation overlap; accept if any matches.","example":"v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="},{"name":"user-agent","in":"header","required":true,"schema":{"type":"string","const":"Monologue-Webhooks/1.0"},"description":"Always `Monologue-Webhooks/1.0`."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookNoteFailedEvent"},"example":{"type":"note.failed","timestamp":"2026-07-07T12:00:03.214823Z","data":{"note_id":"8f14e45f-ceea-467f-a34e-4a3d1e1a89b2","status":"failed","error_message":"Transcription failed: audio file was empty","created_at":"2026-07-07T11:59:41Z","updated_at":"2026-07-07T12:00:03Z","api_url":"https://api.monologue.to/v1/public-api/notes/8f14e45f-ceea-467f-a34e-4a3d1e1a89b2"}}}}},"responses":{"2XX":{"description":"Return any 2xx status within 20 seconds to acknowledge the delivery. For automatic `note.processed` / `note.failed` deliveries, any other status (3xx included - redirects are not followed) or a timeout triggers the retry schedule; manual sends (the creation `ping`, test events, redeliveries) are attempted exactly once. `410 Gone` disables the endpoint immediately in either case."}}}},"ping":{"post":{"tags":["Webhooks"],"summary":"Ping (connectivity check)","description":"A one-off connectivity check sent automatically when you create a webhook endpoint. Signed like every other delivery - a good first event to test your verification against. Acknowledge with a 2xx. Sent exactly once, with no retries: if it does not arrive or fails, use **Send test event** in Settings to try again.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"},"description":"Unique message id (`msg_...`), stable across retries of the same event. Deduplicate on this value.","example":"msg_2f9a4b6c-7d1e-4c3a-9b0f-5e6d7c8b9a01"},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Unix timestamp (seconds) of this delivery attempt.","example":"1767139200"},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"},"description":"Standard Webhooks signature(s): `v1,` + base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}` under your `whsec_` secret. May contain multiple space-delimited signatures during the 24-hour secret-rotation overlap; accept if any matches.","example":"v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="},{"name":"user-agent","in":"header","required":true,"schema":{"type":"string","const":"Monologue-Webhooks/1.0"},"description":"Always `Monologue-Webhooks/1.0`."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookPingEvent"},"example":{"type":"ping","timestamp":"2026-07-07T12:00:03.214823Z","data":{"message":"Monologue webhook ping. Your endpoint is wired up."}}}}},"responses":{"2XX":{"description":"Return any 2xx status within 20 seconds to acknowledge the delivery. For automatic `note.processed` / `note.failed` deliveries, any other status (3xx included - redirects are not followed) or a timeout triggers the retry schedule; manual sends (the creation `ping`, test events, redeliveries) are attempted exactly once. `410 Gone` disables the endpoint immediately in either case."}}}}},"servers":[{"url":"https://api.monologue.to","description":"Production"}]}