1. Sharing
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
        GET
      • Share by principal, or invite by email (owner)
        POST
      • Change someone's role (owner)
        PATCH
      • Remove access (owner, or leave yourself)
        DELETE
      • Cancel a pending invitation (owner)
        DELETE
      • Document invitations to your verified email
        GET
      • Accept a document invitation
        POST
      • Decline a document invitation
        POST
    • 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
      • Register an endpoint (up to 10)
      • One endpoint
      • Delete an endpoint (queued retries are dropped)
    • 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
    • Schemas
      • Error
      • Principal
      • Role
      • Access
      • ContentType
      • Language
      • FileRef
      • Document
      • Tombstone
      • DocumentPage
      • CreateDocument
      • UpdateDocument
      • FileInfo
      • CommitUpload
      • Upload
      • DownloadLink
      • Extracted
      • ExtractionFailed
      • CommittedDocument
      • ExtractedDocument
      • SearchHit
      • SearchPage
      • Export
      • Permission
      • Share
      • ChangeRole
      • Invitation
      • Permissions
      • ReceivedInvitation
      • AcceptedInvitation
      • Me
      • WebhookEventType
      • Webhook
      • CreateWebhook
      • CreatedWebhook
      • WebhookDelivery
      • AudioFormat
      • Speech
      • WordTiming
      • SpeechMarks
      • AudioLink
      • Voice
      • Quota
      • SettingEntry
      • Settings
      • SettingsPatch
      • PatchedSettings
      • OAuthToken
      • OAuthError
  • Handwrite Team
    • Schemas
      • Error
      • Principal
      • Access
      • ContentType
      • Language
      • FileRef
      • Document
      • Tombstone
      • DocumentPage
      • OrgKind
      • OrgRole
      • Organisation
      • CreateOrganisation
      • RenameOrganisation
      • Member
      • AddMember
      • ChangeMember
      • InviteMember
      • OrgInvitation
      • ReceivedOrgInvitation
  • Handwrite Classroom
    • Schemas
      • Error
      • Principal
      • Access
      • ContentType
      • Language
      • FileRef
      • Document
      • Tombstone
      • DocumentPage
      • OrgKind
      • OrgRole
      • Organisation
      • CreateOrganisation
      • RenameOrganisation
      • Member
      • AddMember
      • ChangeMember
      • InviteMember
      • OrgInvitation
      • ReceivedOrgInvitation
  1. Sharing

README — POST /api/v1/documents/{id}/permissions

Share by principal, or invite by email (owner)#

POST /api/v1/documents/{id}/permissions · Operation ID: shareDocument

Purpose and app behavior#

Owner-only: send either a principal or an email plus viewer/editor role. Principal sharing returns 200/201; email always returns 202 pending invitation, irrespective of account existence. Do not tell the user an email invitation granted immediate access. The current implementation does not send invitation email. The invitee must sign in with the matching verified address and open their Handwrite invitation inbox.

Authentication#

Bearer token with permissions:write. 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/documents/REPLACE_DOCUMENT_ID/permissions' \
  -H "Authorization: Bearer $HANDWRITE_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"email":"reader@example.com","role":"viewer"}'

Parameters#

NameLocationRequiredMeaning
idpathYesA document ID (doc_…).
Idempotency-KeyheaderNo1–255 visible ASCII characters (a UUID per operation). A retry with the same key and identical request within 24 hours replays the first 2xx response with Idempotent-Replayed: true; a different request with the key gets 422 idempotency_mismatch; a retry while the first runs gets 409 idempotency_in_progress.

Request body#

application/json (required).
The paired API reference defines the complete schema and alternatives.

Responses#

StatusMeaningBody format
200A principal's role was changed.application/json
201A principal got access.application/json
202An email was invited (always, whether or not it has an account).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
404not_found: it doesn't exist or you can't see it (never 403 for documents you can't see).application/json
409conflict (changed meanwhile, already a member) or idempotency_in_progress (with Retry-After).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:23:58
Previous
README — GET /api/v1/documents/{id}/permissions
Next
README — PATCH /api/v1/documents/{id}/permissions/{principal}
Built with