Skip to content

Developers

Docs API

Read and change pages, databases and comments from your own code. Requests and responses follow Notion's API, so many existing clients work after changing the base URL.

On this page

Working across products — issues, projects, calendar, designs, the links between everything and your other apps' objects? See the Ecosystem API (free on every plan).

Getting started

  1. Docs → Settings → Connections → “New integration”. Pick its capabilities and copy the secret: it is shown once.
  2. Open a page → “•••” → “Connections” and connect the integration. It sees that page and everything under it, nothing else.
  3. Send the secret in the Authorization header.
curl https://zvena.jevflow.net/api/v1/users/me \
  -H "Authorization: Bearer zv_secret_…" \
  -H "Zvena-Version: 2022-06-28"

Rules

  • JSON only, bodies up to 1 MB, at most 100 blocks per request, 2 levels of nesting.
  • About 3 requests a second per integration; over it you get 429 with Retry-After.
  • Ids are accepted with or without dashes. Lists are paginated: start_cursor, page_size (up to 100), next_cursor, has_more.
  • Errors: { object: "error", status, code, message } — unauthorized, restricted_resource, object_not_found, validation_error, invalid_json, rate_limited, conflict_error.
  • An integration's changes reach everyone at once, land in the version history and carry its name (“Last edited by”). The workspace owner's storage quota applies.

Versions and data sources

A database can hold several data sources, each with its own properties, rows and templates. With a Notion-Version (or Zvena-Version) header of 2025-09-03 or later the API speaks as Notion does: a database lists its data_sources, schemas and rows are read through /v1/data_sources, a row's parent is { type: "data_source_id", data_source_id, database_id }, and search returns data sources (filter value "data_source"). With an older version (2022-06-28 by default) nothing changes: each data source reads as a database with its own id, and the first one is the database itself.

Endpoints

GET/v1/usersPeople and bots of the workspace
GET/v1/users/meThis integration's bot user
GET/v1/users/{id}One user
POST/v1/searchPages and databases by title
POST/v1/pagesA sub-page or a database row
GET/v1/pages/{id}A page and its properties
PATCH/v1/pages/{id}Properties, icon, cover, trash
GET/v1/pages/{id}/properties/{property_id}One property (lists paginated)
POST/v1/databasesA new database inside a page
GET/v1/databases/{id}A database and its schema
PATCH/v1/databases/{id}Title and schema properties
POST/v1/databases/{id}/queryRows with filters and sorts (before 2025-09-03)
POST/v1/data_sourcesA new data source in a database (2025-09-03)
GET/v1/data_sources/{id}A data source and its schema
PATCH/v1/data_sources/{id}Title, properties, trash, move to another database
POST/v1/data_sources/{id}/queryA data source's rows with filters and sorts
GET/v1/data_sources/{id}/templatesA data source's page templates
GET/v1/blocks/{id}A block
PATCH/v1/blocks/{id}Update a block
DELETE/v1/blocks/{id}Delete a block (a page goes to the trash)
GET/v1/blocks/{id}/childrenA page's blocks or a block's children
PATCH/v1/blocks/{id}/childrenAppend blocks (at the end or after `after`)
GET/v1/comments?block_id=Discussions of a page or a block
POST/v1/commentsA comment or a reply

Objects

  • Blocks: paragraph, heading_1–3 (is_toggleable), bulleted_list_item, numbered_list_item, to_do, toggle, quote, callout, code, divider, equation, image, video, audio, file, pdf, bookmark, embed, table and table_row, column_list and column, child_page, child_database, link_to_page, synced_block, table_of_contents, breadcrumb.
  • Text: rich_text with annotations (bold, italic, strikethrough, underline, code, color), links and mentions of pages, dates and people.
  • Properties: title, rich_text, number, select, multi_select, status, date, checkbox, url, email, phone_number, files, people, relation, and read-only formula, rollup, created_time, created_by, last_edited_time, last_edited_by, unique_id, button. Place (our extension): { name, address, lat, lon }.
  • Files can be set as https external links only; files uploaded to zvena come back as type: "file" with a permanent URL.
POST https://zvena.jevflow.net/api/v1/databases/{id}/query
{
  "filter": { "and": [
    { "property": "Status", "status": { "equals": "Done" } },
    { "property": "Due", "date": { "past_week": {} } }
  ] },
  "sorts": [{ "property": "Points", "direction": "descending" }]
}

Webhooks

Set an https endpoint and events in the integration's settings: page.created, page.content_updated, page.properties_updated, page.deleted, database.created, database.schema_updated, database.deleted, data_source.created, data_source.schema_updated, data_source.deleted, comment.created. Only events of connected pages arrive, never the integration's own changes.

Every request is signed: X-Zvena-Signature: sha256=<HMAC-SHA256 of the body with the signing secret>. The signing secret is shown once when you save the URL. Failed deliveries are retried after 1 s, 10 s and 1 min; private addresses are never called.

{
  "id": "…", "timestamp": "2026-10-14T12:00:00.000Z",
  "type": "page.properties_updated",
  "workspace_id": "…", "integration_id": "…",
  "entity": { "id": "…", "type": "page" },
  "authors": [{ "id": "…", "type": "person" }],
  "data": { "parent": { "id": "…" } },
  "attempt_number": 1
}

Build on your own workspace. Start free. Add more when you need it.