Recipes across many workspaces
This page is about rolling one recipe template out across many workspaces of the same agency and keeping the result observable afterwards. The deployment sequence itself is in Deploying recipes; what a template is and how it is authored is in Recipe templates.
One template deploys in every workspace
A recipe template belongs to your agency, not to a workspace. The same template_id means the
same template in every workspace of the agency, there is nothing to register, copy or re-create
per workspace, and one template can be deployed in as many workspaces as you like.
Resolve the ids once, from
GET /api/v3.1/automated-recipe-templates/, and
pin them in your own configuration. Re-resolve them before each rollout: templates are created and
edited in the interface, so a template that the list no longer returns has been changed there, not
failed temporarily.
Being able to deploy does not predict the outcome. Deployment succeeds wherever the template is
visible, but the result depends on that workspace's own connections, accounts and data delivery.
The same template can finish complete in one workspace and ready_to_work with degraded: true in
the next. Treat degraded and sources of each recipe as the answer, not the fact that create,
configure and build all returned success.
What is per workspace
| Value | Where it comes from |
|---|---|
| Access token | The token exchange for that workspace |
connection_id | GET /api/v3/datasources/{datasource_name}/connections in that workspace |
Account id | GET /api/v3.1/connections/{connection_id}/accounts/ in that workspace, is_active: true only |
recipe_id | The recipe you create in that workspace |
None of these transfer. A connection or account id read in one workspace does not identify anything
in another, and a PUT that carries it over is rejected. Always read them from the endpoints of the
workspace you are deploying into, and cache the results keyed by workspace.
A token is bound to a single workspace. It lives 30 minutes and every successful request extends that window, so for a fleet plan how tokens are minted, reused and rotated rather than exchanging credentials on every call.
Per workspace the cycle is always the same:
Code
Extraction cost scales with the number of workspaces: each workspace's recipe gets its own extractions, and nothing is shared between workspaces.
Output table names
The output table name is derived from the template title at the moment the recipe is created. You do not choose it, and the recipe keeps it afterwards.
- Names are unique within a pair of agency and workspace. The same template therefore produces the same table name in every workspace. That is expected — do not try to make names unique across the fleet.
- Do not rename the template in the middle of a rollout. Recipes deployed after the rename take the new name, recipes deployed before it keep the old one, and you end up with two names for one template across the fleet. Settle the title before the rollout, or finish the rollout first.
- Deleting a recipe frees its name immediately, whether it is deleted through the API or in the
interface. The exception is recipes that were deleted in the interface earlier, before the
interface switched to hard deletion: if such a recipe had an output table, it still holds the
name. A
view_name_takenconflict then points at a recipe that answers404, and only support can release that name. See Deploying recipes.
To find the physical name of a deployed recipe, go through its datatable_id rather than
recomputing it from the template title; the procedure is in Deploying recipes.
Checking the fleet
One call per workspace is enough:
Code
Every list item from
GET /api/v3.1/automated-recipes/ already carries state,
degraded, not_delivered_reasons, last_build_at and error, so a health check needs no
per-recipe call:
Code
Fetch the recipe detail only for recipes you have already flagged: sources[] is for working out
which source and which account is affected.
| Signal in the list item | What to do |
|---|---|
state: failed | Read error.code and fix the cause; the build error codes are catalogued in Errors |
degraded: true with a reason that needs action | Fix it in the workspace, then run a build again |
degraded: null | The completeness of the last build is unknown, because it predates this API version. Run a build to get an answer |
No outcome noticeably beyond 120 minutes after last_build_at | A build has no hard time limit, but in practice it finishes well inside 120 minutes. If a recipe is still not ready_to_work or failed much later, contact support with the x-im-trace-id of one of your requests |
The reasons that need action in the workspace are connection_unavailable, account_disabled,
permission_denied, extraction_failing, report_type_deprecated and paused, plus
source_failed at the level of a whole source. The full table of reasons and what each one means is
in Deploying recipes.
timed_out is the one to read carefully: it means an extraction did not deliver in time for the
build, not that it is broken. The data may well arrive in the table afterwards, but the status does
not change by itself — degraded: true and the reason stay until the recipe is built again. There
are no automatic rebuilds, so a fresh build is what turns a stale timed_out into a current
answer.
One thing the fleet check cannot see: an extraction that delivered zero rows counts as delivered, so
a recipe can be ready_to_work and not degraded while one account contributes nothing. If per
account coverage matters to you, verify it by querying the output table in your destination.
There are no webhooks for a finished build
No webhook event is emitted when a recipe build finishes. Readiness is found by polling
GET /api/v3.1/automated-recipes/{recipe_id}/ until state
is ready_to_work or failed. Across a fleet, poll the list endpoint per workspace instead of
polling each recipe separately — it returns the same fields for every recipe in one call.
Load
Rate limits apply to this API like any other; see Rate limits. Beyond them, if you are fanning out across dozens or hundreds of workspaces, agree a concurrency ceiling with us before the rollout rather than discovering one during it.
Two practical rules that keep the fan-out cheap:
- Reuse a workspace token for the whole batch of calls in that workspace instead of exchanging credentials per request.
- Never run two creates of the same template in the same workspace at the same time, and spread builds out instead of starting them all at once.

