.md

API keys

Project Settings → API Keys issues the keys everything outside the console authenticates with. The type select silently rewrites the rest of the form, and nothing on it says what separates the three types.

The type decides how the key is checked

Type How it is checked
CLI read/write Holding the key is the permission. Full read and write over the project's files.
SDK readonly Holding the key is the permission. Read-only.
Scoped (custom permissions) The key carries its own permissions and is checked against them on every request.

For the first two, nothing narrows the key. A scoped key — the type the form opens on — is the only one that can be given less than everything. Project viewers have no API Keys entry in Project Settings, and the console API returns them only the read-only keys an app can ship with: SDK readonly keys and the Browser (read-only) key.

Every new project starts with four keys:

  • CLI (CLI read/write) reads and writes everything.
  • SDK Development (SDK readonly) reads everything.
  • Workflow Execution Key (scoped) reads dcupl.lc.json, data/**, models/**, transformers/**, operators/** and scripts/**, and writes data/** and models/**.
  • Browser (read-only) (scoped) reads dcupl.lc.json, models/**, data/**, transformers/** and operators/**, and writes nothing.

The Workflow Execution Key's value is also the project variable dcupl_api_key; it stays on the server. Browser (read-only) is the key for browser apps: it reads only through the dcupl CDN, and the console API refuses it (403). Seeded keys don't count toward your plan's key limit (the counter on the API Keys page still includes them). Projects created before these four existed keep the keys they had, which count toward the limit: CLI and SDK Development and, on all but the oldest projects, a Workflow Execution Key that reads only dcupl.lc.json, data/** and models/**.

The Workflow Execution Key is also the key a dcupl Instance step starts with: a step added in the workflow editor carries the key's id as config.apiKey in its Init Options, and deploying the workflow resolves the id to the key, so the step's loader can fetch a private project's files. That is why the key reads transformers/**, operators/** and scripts/**. A step written into the template by hand has no key until you add one. On a project created before the four seeded keys, the preset is that project's own Workflow Execution Key, which reads only dcupl.lc.json, data/** and models/**; a project without a key named Workflow Execution Key gets no preset, and its steps start with no key at all. If such a project is private, put the UID of a key that reads every file its loader declares in the step.

A key cannot be edited: to change its type or patterns, create a new key and delete the old one. Replacing the Workflow Execution Key this way leaves the old value in dcupl_api_key and the old key's id in the workflow steps that use it: update both, then redeploy those workflows. Set custom value on the form lets you choose the key string (at least 16 characters; letters, digits, - and _); otherwise one is generated.

A scoped key carries globs over your files

A scoped key's file read patterns are globs matched against paths in your project. Its file write patterns cover write, delete, move and copy. The form starts a scoped key with dcupl.lc.json, data/** and models/** as read patterns and no write pattern; add transformers/**, operators/** or scripts/** when the app loads them. Two further switches, Execute Workflows and Create Runners, are capabilities rather than paths. Execute Workflows decides which keys a workflow's request trigger can require: the trigger's key picker lists only scoped keys with it switched on. Create Runners has no effect yet: no service checks it.

A path that no pattern matches is simply left out of the key. There is no warning in the form, because the form does not know what the key will be used for.

The globs must cover everything the app loads

flowchart LR
  K["Scoped key"] --> LC["dcupl.lc.json"]
  LC --> RES["every declared resource<br/>models · data · transformers · scripts · operators"]
  RES --> G{"path matches<br/>a read pattern?"}
  G -->|yes| OK["loads"]
  G -->|no| FAIL["403 — that resource is missing from the run"]

A project is private when Private CDN is on for it: the CDN then serves its files only to requests that carry one of the project's keys. New projects are private by default. On a project without Private CDN the CDN serves the files without a key, so a scoped key's read patterns do not limit what an app can load. The console does not show the setting. Once on, it stays on through plan changes; a project created before projects became private by default stays public unless its plan includes Private CDN.

A key is only tested when something loads with it. The loader fetches your dcupl.lc.json and every resource it declares, so on a private project one uncovered path — a scripts/ folder, say — answers 403 at load time, long after the key looked fine in this form. The loader records that resource as an InvalidResource loader error and loads the rest, so the app comes up without it: no scripts, or a model with no rows. Only an uncovered dcupl.lc.json fails the whole load. The Browser (read-only) key, for example, does not cover scripts/**: a browser app whose loader declares script resources under scripts/ needs a scoped key of its own.

Think about coverage, not syntax. List the resource URLs in your loader config and check each one against the patterns before you save.

Who uses a key

  • The SDK — an app loading a private project passes the key to the loader, which appends it to every hosted resource request. A browser app ships its key to every visitor, so give it the Browser (read-only) key (or another scoped key that reads only what the app loads), and keep keys that can write on a server.
  • The CLI — a CLI read/write key authenticates dcupl files push and pull and the dcupl workflow commands (deploy, test, history, …); the console API accepts only this key type for workflow deployment.
  • Workflows — a dcupl Instance step loads the project with the key in its Init Options (config.apiKey, preset to the Workflow Execution Key in the editor when the project has one; for another key, put that key's UID, shown in its details on the API Keys page, in its place). A dcupl Files step carries a key of its own. A scoped key needs the matching file patterns. A request trigger with authentication accepts the keys selected on it, and the trigger offers only scoped keys with Execute Workflows.
  • REST APIs — a deployed instance loads its data with the key configured on it. The template form's Api Key picker offers SDK readonly keys and scoped keys that have at least one read pattern (the limit is the picker's: a template edited as JSON deploys with any key it holds). A scoped key must cover everything the instance loads. The form warns only when the template has endpoints and the key cannot read the script files the template's application schedules (or scripts/** while it schedules none); it never checks loader data or models.