1. Webhooks
Handwrite
  • Handwrite Regular Accounts
    • Start here — Handwrite for outside developers
    • API specification notes
    • Socket specification notes
    • Account
      • README — GET /api/v1/me
      • README — DELETE /api/v1/me
      • README — GET /api/v1/me/policy
      • README — GET /api/v1/me/usage
      • Account API — README
      • Who this credential acts for
      • Delete the account (after a 30-day grace period)
      • What your teams' and classes' policies allow
      • Your own usage, and what your teams and classes counted
    • Documents
      • README — GET /api/v1/documents
      • README — POST /api/v1/documents
      • README — GET /api/v1/documents/search
      • README — GET /api/v1/documents/{id}
      • README — PATCH /api/v1/documents/{id}
      • README — DELETE /api/v1/documents/{id}
      • README — GET /api/v1/documents/{id}/content
      • README — PUT /api/v1/documents/{id}/content
      • README — POST /api/v1/documents/{id}/live
      • README — GET /api/v1/export
      • Documents API — README
      • List your documents (or shared, or changes since)
      • Create a document
      • Search your own and shared documents
      • A document's metadata
      • Change title, text, content type or language
      • Delete a document (owner)
      • The document's text
      • Replace the text
      • Join the document's live co-editing room
      • Every document you own, with its text
    • Files
      • README — GET /api/v1/documents/{id}/file
      • README — POST /api/v1/documents/{id}/file
      • README — POST /api/v1/documents/{id}/file/commit
      • README — POST /api/v1/documents/{id}/extract
      • Files API — README
      • Download the original file
      • Start uploading the original file
      • Make an uploaded file the document's file
      • Replace the text with the file's text
    • Audio
      • README — GET /api/v1/documents/{id}/audio
      • README — POST /api/v1/audio/stream
      • README — POST /api/v1/audio/speech
      • README — GET /api/v1/voices
      • README — GET /api/v1/quota
      • Audio API — README
      • The whole document as one audio file
      • Stream speech as it's made
      • Speech with word timings (read-along)
      • Voices you can use
      • Characters left, limit, plan and reset time
    • Sharing
      • README — GET /api/v1/documents/{id}/permissions
      • README — POST /api/v1/documents/{id}/permissions
      • README — PATCH /api/v1/documents/{id}/permissions/{principal}
      • README — DELETE /api/v1/documents/{id}/permissions/{principal}
      • README — DELETE /api/v1/documents/{id}/invitations/{inviteId}
      • README — GET /api/v1/invitations
      • README — POST /api/v1/invitations/{id}/accept
      • README — POST /api/v1/invitations/{id}/decline
      • Sharing API — README
      • Who a document is shared with
      • Share by principal, or invite by email (owner)
      • Change someone's role (owner)
      • Remove access (owner, or leave yourself)
      • Cancel a pending invitation (owner)
      • Document invitations to your verified email
      • Accept a document invitation
      • Decline a document invitation
    • Settings
      • README — GET /api/v1/settings
      • README — PATCH /api/v1/settings
      • Settings API — README
      • Synced app and reader settings
      • Change settings (per key, the newer updatedAt wins)
    • Webhooks
      • Incoming webhook delivery — README
      • README — GET /api/v1/webhooks
      • README — POST /api/v1/webhooks
      • README — GET /api/v1/webhooks/{id}
      • README — DELETE /api/v1/webhooks/{id}
      • Webhooks API — README
      • Your webhook endpoints
        GET
      • Register an endpoint (up to 10)
        POST
      • One endpoint
        GET
      • Delete an endpoint (queued retries are dropped)
        DELETE
    • Meta
      • README — GET /api/v1/openapi.json
      • Meta API — README
      • This OpenAPI description
    • OAuth
      • README — POST /api/oauth/token
      • README — POST /api/oauth/revoke
      • OAuth API — README
      • Exchange a code, or refresh
      • Revoke a token (RFC 7009)
    • Live socket
      • Live document socket — README
    • A document or sharing event
  1. Webhooks

README — POST /api/v1/webhooks

Register an endpoint (up to 10)

POST /api/v1/webhooks · Operation ID: createWebhook

Purpose and app behavior

Compatibility note (2026-10-26): the published OpenAPI still lists this operation, but current working-tree code rejects new personal-account receivers with 403 webhooks_moved. New receivers belong to teams/classes and are created by an administrator through the organisation Developer tab. Previously created personal receivers continue to work in that code. This change has not been verified against the live runtime. The reference below preserves the published contract; do not assume new personal registration is available. Where creation is supported, store the returned signing secret immediately; it is shown only once. Maximum 10 endpoints. Document-limited tokens cannot register receivers. Validate signatures on raw bytes and durably deduplicate event IDs before processing.

Tokens limited to chosen documents can't register endpoints (403). Deliveries are signed: Handwrite-Signature: t=,v1=<hex HMAC-SHA256 of "t.body">.

Authentication

Bearer token with webhooks:manage. Resource access and effective policy still apply.

Example request

Replace all REPLACE_* placeholders and environment values with data for your authorized test account. Use a new UUID in IDEMPOTENCY_KEY for each logical action where shown; use the actual latest revision for If-Match. Examples of writes change real data if run.

curl --fail-with-body -X POST 'https://handwrites.io/api/v1/webhooks' \
  -H "Authorization: Bearer $HANDWRITE_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"url":"https://example.com/handwrite/webhook","events":["document.updated"]}'

Request body

application/json (required).

FieldRequiredMeaning
urlYeshttps only, port 443 or 1024+, resolving only to public addresses.
eventsYesarray

Responses

StatusMeaningBody format
201The endpoint and its secret, shown once.application/json
400invalid_request (the message names the field), validation_failed.application/json
401unauthorized: no token, or it's invalid, revoked or expired.application/json
403insufficient_scope, forbidden (you can see it but not do this), app_test_restricted, account_deleted (the account is scheduled for deletion; any request).application/json
422limit_reached, idempotency_mismatch, unreadable_file, no_text, empty_document.application/json
429rate_limited (burst or daily cap) or quota_exceeded (no characters left).application/json
500internal_error.application/json

Use the paired API reference for complete request/response schemas. See API specification notes for rate limits, error handling, safe retries and additional policy/plan failures. For binary or empty responses, do not call a JSON parser.

Modified at 2026-10-26 13:12:48
Previous
README — GET /api/v1/webhooks
Next
README — GET /api/v1/webhooks/{id}
Built with