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 resourceId values 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 ensures the same records are updated rather than recreated.
Three properties follow. The script becomes idempotent. It becomes decoupled from the workspace — multiple mapping tables allow deploying the same script to several workspaces. And since it is code, it supports variables and loops: the example given is building ten teams of identical structure while changing only a few nouns.
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, a call now being a batch rather than a single entity.
The product assumes the agent. The SDK is presented as built « for you or your coding agent », and the onboarding path consists of letting an agent read the SDK's README. A typed state descriptor is indeed a better tool for an agent than a series of imperative 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 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. It is the Terraform model, applied to pages, databases, and teams rather than cloud resources.
The central mechanism — the resource identifier, and why it does everything. the script contains no Notion identifier. It uses resourceId values 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 — redeploying 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 by logical identifier is what turns an API script into a reusable state descriptor. This is exactly the role resource addresses play in Terraform state.
The API contract, in two steps (asynchronous).POST /v1/infra_as_code (fields intents — a 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 worth knowing before trying it.
Mandatory personal access tokens. , rather than 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, folded 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 on the assumption that 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 correctable by redeployment 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 does not 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 real state tool knows how to delete what is no longer declared — here, nothing indicates this, which suggests an additive reconciliation and therefore possible drift between the script and the actual workspace.
No "plan" mode. and no preview before applying. One deploys and observes.
No handling of concurrency. two simultaneous deployments to 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 the observation-based dating in this fiche.
Tech-watch angle — why this matters beyond Notion. it is one more signal of the declarative model migrating out of infrastructure. After the cloud, documentary workspaces; and the acknowledged trigger 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 in [[isenberg-meng-to-google-design-md-design-team-in-a-file-2026-05-06]], and to the versioned-specification discipline in [[lassiege-usine-logicielle-heure-ia-2026-07-28]].
Meta / cross-references. the question of the personal token and acting on someone else's behalf in [[girard-acp-deux-protocoles-un-sigle-2026-08-02]]; an agent's 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