Reference

The Papyra API

Everything the web app does, your scripts can do. 109 operations across 90 paths, described by an OpenAPI 3.1.1 document your own instance publishes.

Authenticating

Create a personal access token in Settings → API Keys. It is shown once, at creation, because Papyra stores only a hash of it.

Send it as X-API-Key, or as Authorization: Bearer if that suits your client better — the two are equivalent. It is an opaque token, nota JWT; there is nothing to decode.

Terminal
# Settings → API Keys creates the token. It is shown once.
export PAPYRA=https://notes.example.com
export PAPYRA_TOKEN=pk_live_...

curl -s "$PAPYRA/api/notes" -H "X-API-Key: $PAPYRA_TOKEN"

A token inherits the account that made it, including its folder. It can reach exactly that person's notes and nothing else.

Creating and updating a note

There is no POST /api/notes. A note's id is its filename on disk, and you choose it, so creating and updating are the same call:PUT /api/notes/{id}. Writing to an id that does not exist creates it; writing to one that does replaces it, snapshotting the previous revision first.

Terminal
# There is no POST for notes. A new note is a PUT to an id you choose,
# and the same call updates an existing one.
curl -s -X PUT "$PAPYRA/api/notes/shopping-list" \
  -H "X-API-Key: $PAPYRA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "title": "Shopping list",
        "body": "- [ ] Coffee\n- [ ] Olive oil",
        "tags": ["home"],
        "kind": "todo"
      }'

Searching

Terminal
# Keyword search (Lucene), then meaning-based search over embeddings.
curl -s "$PAPYRA/api/search?q=pricing"          -H "X-API-Key: $PAPYRA_TOKEN"
curl -s "$PAPYRA/api/search/semantic?q=pricing" -H "X-API-Key: $PAPYRA_TOKEN"

Semantic search needs an embedding model configured — seethe assistant. Keyword search always works.

Trying requests

This page is a reference, not a console — there is no public Papyra instance for it to call. Your own instance serves a live, interactive portal at/docs, where you paste your token and actually issue requests. That is deliberately reachable in production so self-hosters have real documentation for their own server.

The document behind this page is at /openapi/v1.json on your instance — point any OpenAPI tool at it.

Two things to know while reading

  • Everything needs authentication except /api/shared/{token}, which is the public share-link surface and is anonymous by design.
  • Only 26 of 109 operations carry a written summary today. The rest are listed with their real shape — method, path, parameters and request body — but no prose. That gap istracked upstream.

Auth17

  • POST/api/auth/accept-inviteRedeem an invitation and create the account

    Request body — ResetPasswordRequest

    • tokenstring · required
    • passwordstring · required

    Responses

    200

  • GET/api/auth/avatar

    Responses

    200

  • POST/api/auth/avatar

    Responses

    200

  • GET/api/auth/avatar/{username}

    Parameters

    • usernamepath · string · required

    Responses

    200

  • POST/api/auth/forgot-passwordRequest a password reset link

    Request body — ForgotPasswordRequest

    • usernameOrEmailstring · required

    Responses

    200

  • POST/api/auth/login

    Request body — LoginRequest

    • usernamestring · required
    • passwordstring · required

    Responses

    200

  • GET/api/auth/login/sso

    Responses

    200

  • POST/api/auth/logout

    Responses

    200

  • GET/api/auth/me

    Responses

    200

  • GET/api/auth/notifications

    Responses

    200

  • PUT/api/auth/notifications

    Request body — NotificationPrefsWrite

    • mentionboolean · required
    • shareboolean · required

    Responses

    200

  • POST/api/auth/password

    Request body — PasswordRequest

    • currentstring · required
    • nextstring · required

    Responses

    200

  • PUT/api/auth/profile

    Request body — ProfileRequest

    • namestring · required
    • emailstring · required

    Responses

    200

  • GET/api/auth/providers

    Responses

    200

  • POST/api/auth/reset-passwordSet a new password from a reset link

    Request body — ResetPasswordRequest

    • tokenstring · required
    • passwordstring · required

    Responses

    200

  • POST/api/auth/setup

    Request body — SetupRequest

    • usernamestring · required
    • namestring · required
    • emailstring · required
    • passwordstring · required

    Responses

    200

  • GET/api/auth/token/{token}

    Parameters

    • tokenpath · string · required

    Responses

    200

Notes17

  • GET/api/notesList notes

    Returns the caller's notes (metadata + body) from the in-memory vault. Optional from/to filter by last-modified date.

    Parameters

    • fromquery · date-time
    • toquery · date-time

    Responses

    200

  • PUT/api/notes/{id}

    Parameters

    • idpath · string · required

    Request body — NoteWrite

    • titlestring · required
    • tagsstring[] · required
    • colorstring · required
    • pinnedboolean · required
    • archivedboolean · required
    • bodystring · required
    • kindstring
    • secureboolean

    Responses

    200

  • DELETE/api/notes/{id}

    Parameters

    • idpath · string · required

    Responses

    200

  • GET/api/notes/{id}/blocksList a note's block anchors

    Every `^id` anchor in the note, in document order, for building a block reference.

    Parameters

    • idpath · string · required

    Responses

    200

  • GET/api/notes/{id}/blocks/{blockId}Resolve one anchored block

    Returns only the anchored block's text — never the surrounding note body.

    Parameters

    • idpath · string · required
    • blockIdpath · string · required

    Responses

    200

  • POST/api/notes/{id}/restore/{snapshotId}

    Parameters

    • idpath · string · required
    • snapshotIdpath · string · required

    Responses

    200

  • GET/api/notes/{id}/secureReveal a secure note's body

    Requires a valid X-Unlock-Token from a successful WebAuthn assertion; 401 otherwise.

    Parameters

    • idpath · string · required

    Responses

    200

  • GET/api/notes/{id}/shares

    Parameters

    • idpath · string · required

    Responses

    200

  • POST/api/notes/{id}/shares

    Parameters

    • idpath · string · required

    Request body — ShareWrite

    • kindstring · required
    • accessstring · required
    • granteeUsernamestring · required
    • expiresUtcdate-time · required
    • maxViewsinteger | string · required

    Responses

    200

  • GET/api/notes/{id}/snapshots

    Parameters

    • idpath · string · required

    Responses

    200

  • GET/api/notes/{id}/snapshots/{snapshotId}

    Parameters

    • idpath · string · required
    • snapshotIdpath · string · required

    Responses

    200

  • POST/api/notes/{id}/trash

    Parameters

    • idpath · string · required

    Responses

    200

  • POST/api/notes/{id}/untrash

    Parameters

    • idpath · string · required

    Responses

    200

  • GET/api/notes/activityNote activity heatmap

    Responses

    200

  • GET/api/notes/order

    Responses

    200

  • PUT/api/notes/order

    Request body — OrderWrite

    • entriesOrderEntryDto[] · required

    Responses

    200

AI7

  • POST/api/ai/chat

    Request body — AiChatRequest

    • questionstring · required
    • sessionIdinteger | string

    Responses

    200

  • GET/api/ai/modelsDownloadable local models

    Responses

    200

  • GET/api/ai/sessions

    Responses

    200

  • GET/api/ai/sessions/{id}

    Parameters

    • idpath · integer · required

    Responses

    200

  • PATCH/api/ai/sessions/{id}

    Parameters

    • idpath · integer · required

    Request body — ChatSessionRename

    • titlestring · required

    Responses

    200

  • DELETE/api/ai/sessions/{id}

    Parameters

    • idpath · integer · required

    Responses

    200

  • GET/api/ai/statusWhether the assistant can answer, and why not

    Responses

    200

Categories3

  • GET/api/categories

    Responses

    200

  • POST/api/categories

    Request body — CategoryWrite

    • namestring · required
    • colorstring · required

    Responses

    200

  • DELETE/api/categories/{name}

    Parameters

    • namepath · string · required

    Responses

    200

Collections4

  • GET/api/collections

    Responses

    200

  • POST/api/collections

    Request body — SmartCollectionWrite

    • namestring · required
    • rulesJsonstring · required

    Responses

    200

  • DELETE/api/collections/{id}

    Parameters

    • idpath · integer · required

    Responses

    200

  • GET/api/collections/{id}/notes

    Parameters

    • idpath · integer · required

    Responses

    200

Sharing9

  • GET/api/shared/{token}no auth

    Parameters

    • tokenpath · string · required

    Responses

    200

  • PUT/api/shared/{token}no auth

    Parameters

    • tokenpath · string · required

    Request body — SharedBodyWrite

    • bodystring · required

    Responses

    200

  • GET/api/shared/{token}/media/{filename}no auth

    Parameters

    • tokenpath · string · required
    • filenamepath · string · required

    Responses

    200

  • DELETE/api/shares/{shareId}

    Parameters

    • shareIdpath · integer · required

    Responses

    200

  • GET/api/shares/incoming

    Responses

    200

  • GET/api/shares/incoming/{shareId}

    Parameters

    • shareIdpath · integer · required

    Responses

    200

  • PUT/api/shares/incoming/{shareId}

    Parameters

    • shareIdpath · integer · required

    Request body — SharedBodyWrite

    • bodystring · required

    Responses

    200

  • GET/api/shares/incoming/{shareId}/media/{filename}

    Parameters

    • shareIdpath · integer · required
    • filenamepath · string · required

    Responses

    200

  • GET/api/shares/summary

    Responses

    200

Inbox3

  • GET/api/inboxList inbox entries

    Each entry is one anchored block another user pinged you with, already resolved.

    Responses

    200

  • DELETE/api/inbox/{id}Dismiss an inbox entry

    Parameters

    • idpath · integer · required

    Responses

    200

  • POST/api/inbox/readMark all inbox entries read

    Responses

    200

Media2

  • GET/api/media/{filename}

    Parameters

    • filenamepath · string · required

    Responses

    200

  • POST/api/media/upload

    Parameters

    • noteIdquery · string

    Responses

    200

Import & export3

  • GET/api/export

    Responses

    200

  • POST/api/import/{provider}

    Parameters

    • providerpath · string · required

    Responses

    200

  • POST/api/import/quick

    Responses

    200

Backups2

  • POST/api/backups/generateGenerate encrypted backup

    Verifies the account password, then streams an AES-GCM encrypted .papyra-vault of the caller's notes + media.

    Request body — BackupRequest

    • passwordstring · required

    Responses

    200

  • POST/api/backups/restoreRestore from encrypted backup

    Decrypts an uploaded .papyra-vault (multipart: password + file) and replaces the caller's notes + media, then rebuilds the cache.

    Responses

    200

Git3

  • GET/api/git

    Responses

    200

  • PUT/api/gitConfigure git backup of your own vault

    Sets the remote for a mirror of the caller's vault only. Papyra's own state (.papyra/, .trash/) is gitignored. Each account has its own repository and its own credentials; no account can configure or trigger another's.

    Request body — GitConfigWrite

    • remoteUrlstring · required
    • branchstring · required
    • tokenstring · required

    Responses

    200

  • POST/api/git/syncBack up your vault now

    Stages, commits and pushes the caller's vault. Returns status 'pushed', 'clean', or 'conflict' — a diverged remote is never force-pushed; the conflict flag is raised instead and the remote is left untouched.

    Responses

    200

Webhooks3

  • GET/api/webhooks

    Responses

    200

  • POST/api/webhooks

    Request body — WebhookWrite

    • eventstring · required
    • urlstring · required
    • secretstring · required

    Responses

    200

  • DELETE/api/webhooks/{id}

    Parameters

    • idpath · integer · required

    Responses

    200

Settings2

  • GET/api/settings

    Responses

    200

  • PUT/api/settings

    Request body — SettingsRequest

    • trashRetentionDaysinteger | string · required

    Responses

    200

Conflicts3

  • GET/api/conflicts

    Responses

    200

  • GET/api/conflicts/{id}

    Parameters

    • idpath · string · required

    Responses

    200

  • POST/api/conflicts/{id}/resolve

    Parameters

    • idpath · string · required

    Request body — ResolveConflictRequest

    • keepstring · required

    Responses

    200

API Keys3

  • GET/api/keys

    Responses

    200

  • POST/api/keysCreate API key

    Generates a personal access token. The raw token is returned once — store it; only its hash is kept.

    Request body — ApiKeyWrite

    • namestring · required

    Responses

    200

  • DELETE/api/keys/{id}

    Parameters

    • idpath · integer · required

    Responses

    200

Directory1

WebAuthn6

  • POST/api/auth/webauthn/challenge

    Responses

    200

  • GET/api/auth/webauthn/credentials

    Responses

    200

  • DELETE/api/auth/webauthn/credentials/{id}

    Parameters

    • idpath · integer · required

    Responses

    200

  • POST/api/auth/webauthn/register/challenge

    Responses

    200

  • POST/api/auth/webauthn/register/verify

    Request body — WebAuthnRegisterRequest

    • responseobject · required
    • namestring · required

    Responses

    200

  • POST/api/auth/webauthn/verify

    Request body — WebAuthnAssertRequest

    • responseobject · required

    Responses

    200

Admin18

  • GET/api/ai/config

    Responses

    200

  • PUT/api/ai/configConfigure the AI provider (admin)admin

    Selects the chat and embedding backends and stores their API keys. Takes effect immediately — AiClient re-reads its settings when the config version bumps.

    Request body — AiConfigWrite

    • chatProviderstring · required
    • embedProviderstring · required
    • ollamaBaseUrlstring · required
    • ollamaChatModelstring · required
    • ollamaEmbedModelstring · required
    • openAiBaseUrlstring · required
    • openAiChatModelstring · required
    • openAiEmbedModelstring · required
    • openAiKeystring · required
    • anthropicChatModelstring · required
    • anthropicKeystring · required

    Responses

    200

  • POST/api/ai/pullDownload a local model (admin)admin

    Request body — AiPullRequest

    • modelstring · required

    Responses

    200

  • GET/api/auth/oidc

    Responses

    200

  • PUT/api/auth/oidcConfigure SSO (admin)admin

    Stores the OIDC authority, client id and secret. Takes effect immediately — the cached authentication options for the `oidc` scheme are evicted on save.

    Request body — OidcConfigWrite

    • enabledboolean · required
    • authoritystring · required
    • clientIdstring · required
    • clientSecretstring · required
    • displayNamestring · required

    Responses

    200

  • GET/api/auth/smtp

    Responses

    200

  • PUT/api/auth/smtpConfigure outbound email (admin)admin

    Request body — SmtpConfigWrite

    • enabledboolean · required
    • hoststring · required
    • portinteger | string · required
    • useSslboolean · required
    • usernamestring · required
    • passwordstring · required
    • fromAddressstring · required
    • fromNamestring · required
    • publicUrlstring · required

    Responses

    200

  • POST/api/auth/smtp/inviteInvite a user by email (admin)admin

    Request body — InviteRequest

    • usernamestring · required
    • emailstring · required
    • rolestring · required

    Responses

    200

  • POST/api/auth/smtp/testSend a test email (admin)admin

    Request body — SmtpTestRequest

    • tostring · required

    Responses

    200

  • GET/api/auth/users

    Responses

    200

  • POST/api/auth/users

    Request body — ProvisionRequest

    • usernamestring · required
    • namestring · required
    • emailstring · required
    • passwordstring · required
    • rolestring · required
    • sendEmailboolean

    Responses

    200

  • DELETE/api/auth/users/{id}

    Parameters

    • idpath · integer · required

    Responses

    200

  • POST/api/auth/users/{id}/recovery-link

    Parameters

    • idpath · integer · required

    Request body — RecoveryLinkRequest

    • sendEmailboolean

    Responses

    200

  • POST/api/auth/users/{id}/reset

    Parameters

    • idpath · integer · required

    Request body — ResetRequest

    • passwordstring · required
    • sendEmailboolean

    Responses

    200

  • GET/api/jobs

    Responses

    200

  • POST/api/jobs/{id}/run

    Parameters

    • idpath · string · required

    Responses

    200

  • POST/api/system/rebuild-embeddings

    Responses

    200

  • POST/api/system/rebuild-index

    Responses

    200

System1

  • POST/api/system/prune-mediaPrune unreferenced media now (admin)admin

    Moves media files that no live note references into the owning tenant's .trash and reports how many moved. Same sweep the nightly background service runs; nothing is deleted outright.

    Responses

    200

Creating tokens