Notion as Code documentation, a product in closed alpha, accessed on August 3, 2026 on the Notion Ambassadors workspace — with no author or date, and a warning recommending trying it on a fresh workspace and cautioning about possible breaking changes.
The principle is infrastructure as code applied to a documentary workspace: « Instead of having to make individual public API requests, you can describe the final state and we handle updating your workspace to match. » Two building blocks: a TypeScript SDK to describe the desired state, and the /v1/infra_as_code endpoint to deploy it.
Instead of having to make individual public API requests, you can describe the final state and we handle updating your workspace to match.
— **Notion** — documentation produit publiée sur l'espace public **Notion Ambassadors**. **Aucun auteur nommé , app.notion.com
The mechanism that carries everything is identifier indirection. The script contains no Notion identifier: it declares resourceIds chosen by the author. The first deployment returns a mapping table between these logical identifiers and the records actually created; passed back on subsequent calls, it makes the same records updated rather than recreated.
Three properties follow. The script becomes idempotent. It becomes decoupled from the workspace — multiple mapping tables allow the same script to be deployed across several workspaces. And since it is code, it supports variables and loops: the given example is building ten teams of identical structure while changing only a few names.
The API contract is asynchronous: a POST returns a taskId, which is polled until completion; the response carries the mapping tables to persist — the equivalent of a state file.
Two operational differences: the product requires personal access tokens rather than the usual bot tokens, which attributes actions to a person rather than an integration; and the rate limit drops to 5 requests per minute, since a call is now a batch rather than a single entity.
The product assumes an agent. The SDK is presented as built « for you or your coding agent », and the onboarding path is to let an agent read the SDK's README. A typed state descriptor is indeed a better tool for an agent than a series of imperative API calls: the error there is replayable rather than cumulative.
⚠️ What's missing: no mention of deleting elements removed from the script, no preview mode before applying, nothing on concurrency, and no date on documentation that is bound to change.
Key takeaways
⭐ What it is, in one sentence.infrastructure as code for a documentary workspace. The desired final state is described in TypeScript, and Notion reconciles the workspace to match it. This is the Terraform model, applied to pages, databases, and teams rather than cloud resources.
⭐⭐ The core mechanism — the resource identifier, and why it does everything. the script contains no Notion identifier. It uses resourceIds chosen by the author. The first deployment returns a mapping tableresourceId → RecordPointer, which is then passed back via existingResources / existingProperties. Three properties follow from this, and they are inseparable: 1. Idempotence — re-deploying updates instead of recreating. 2. Decoupling from the workspace — « since the script is not coupled to one workspace, you can easily have multiple mappings… allowing you to use the same script to deploy many workspaces »: one mapping table per workspace, a single script. 3. Programmability — it is code, hence variables and loops: « build 10 teams that all have a very similar structure and just need some nouns renamed ». → Indirection through a logical identifier is what turns an API script into a reusable state descriptor. This is exactly the role resource addresses play in a Terraform state.
The API contract, in two steps (asynchronous).POST /v1/infra_as_code (fields intents — the serialized JSON representation of the script —, existingResources, existingProperties) returns a taskId; GET /v1/async_tasks/{taskId} is polled until status: succeeded, the response carrying createdRecordCounts, resourceIdToPointerMappings, and resourceIdToPropertyIdMappings. The two output mapping tables are what must be persisted — they are the equivalent of a state file.
Two operational differences to know before trying it.
Personal access tokens are mandatory. , not the public API's usual bot tokens. ⚠️ A consequence the page does not discuss: actions are attributed to a person, not an integration — raising the same accountability question as « who consumes, and on whose behalf » in [[girard-acp-deux-protocoles-un-sigle-2026-08-02]]. An agent that deploys with an administrator's personal token acts on their behalf.
5 requests per minute. , « since this API is not a 1 request → 1 entity created or updated ». The rate is lowered because a call is a batch.
⭐ The mention of agents, woven in without emphasis.« A typescript SDK for you or your coding agent to describe what you want in your Notion workspace », and the recommended path is to clone the SDK and then let « either you or your favorite coding agent » read the README. → The product is designed assuming an agent will use it, and the typed SDK is precisely what makes this safe: the types constrain what the agent can describe, and reconciliation makes an error fixable by re-deployment rather than manual cleanup. A typed state descriptor is a far better tool for an agent than a series of imperative API calls — the error there is replayable, not cumulative.
Stated limitations. can only create or update within an existing workspace (unable to create a workspace); not all entities are covered — refer to the SDK's type definition file, with high-level primitives expected to work; lowered rate limit.
⚠️ What the page doesn't say, and should be kept in mind.
No mention of destruction. The API "creates or updates." What happens to an element removed from the script? A true state-management tool knows how to delete what is no longer declared — here, nothing indicates this, which suggests an additive reconciliation and thus possible drift between the script and the actual workspace.
No "plan" mode. or preview before applying. One deploys and observes.
No concurrency handling. two simultaneous deployments on the same workspace are not discussed.
No author, no date. For evolving alpha documentation, this is a gap that will make any citation quickly outdated — hence dating this note by observation.
Tech-watch angle — why this matters beyond Notion. this is one more signal of the declarative model migrating out of infrastructure. After the cloud, documentary workspaces; and the acknowledged driver is the coding agent, which needs a describable, typed, replayable format rather than a sequence of actions. Worth relating to the "one file rather than one team" logic of [[isenberg-meng-to-google-design-md-design-team-in-a-file-2026-05-06]], and to the versioned-specification discipline of [[lassiege-usine-logicielle-heure-ia-2026-07-28]].
Meta / cross-links. the personal-token and acting-on-behalf-of-others question in [[girard-acp-deux-protocoles-un-sigle-2026-08-02]]; agent identity and scope of action in [[uber-engineering-agent-identity-crisis-zero-trust-spire-2026-05-21]] and [[valente-zalewski-beyond-zero-enterprise-security-ai-era-2026-07-20]]; agent-driven declarative artifacts in [[isenberg-meng-to-google-design-md-design-team-in-a-file-2026-05-06]].
Attributed claims
the product is under development, subject to breaking changes, and limited to creating or updating within an existing workspace
— Notion as Code
The knowledge graph extracted from this fiche — 4 entities, 12 relations.
In this graph :Notion as Code · How to use Notion as Code · identifiant de ressource logique · Notion