Moving recipes to v3.1
This page is for integrations that already call the v3 automated recipe operations. It lists what changes, what stays the same, and in what order to move.
Nothing has to be recreated: recipes deployed through v3 are readable and manageable through v3.1 as they are.
What changes in the URL
Replace the version segment and keep everything else:
Code
Code
Authentication does not change. The same bearer token from
POST /api/v3/token works on v3.1, and the workspace is
still the one the token was issued for. With cookie authentication, keep sending the workspace id
in the X-IM-WORKSPACE-ID header.
Every path still ends with a slash, exactly as in v3. A 301 means the slash is missing from
your URL, and most HTTP clients follow that redirect by turning a POST into a GET and dropping
the body.
Operation by operation:
The two agency-level recipe operations, GET /api/v3/recipes/ and
POST /api/v3/workspaces/{id}/recipes, are not part of this move.
They are not automated recipe operations, they keep their own authentication, and they stay on v3.
State values
The state of a recipe is now a lower-case machine value instead of a display string:
| v3 | v3.1 |
|---|---|
Extracting Data | extracting_data |
Building Dependencies | building_dependencies |
Ready to work | ready_to_work |
Failed | failed |
The new values are used both in responses and in the ?state= filter of
GET /api/v3.1/automated-recipes/:
Code
An old value in the filter is rejected:
Code
In v3 the same filter with an unknown value returned an empty page, so a client that kept sending
Ready to work would quietly see no recipes. In v3.1 it gets a 400 instead.
What else is different
| In v3 | In v3.1 |
|---|---|
| Errors came in several shapes, and some paths answered with an HTML page | One shape for every error, {code, message, details}, always JSON. See Errors |
A request that contradicted the current state of the recipe answered 400 | 409, including an attempt to drop a data source, a connection or an account |
Many failures answered 400 with free-form text and no code | A specific code from the catalogue, or 500 internal_error |
The extraction-table check answered 503 when the workspace had no destination | 409 no_active_destination |
Create answered 400 when the output table could not be reserved | 503 data_table_reservation_failed |
POST returned a trimmed object | 201 with the full recipe |
PUT returned 200 with an empty body | 200 with the recipe as it now stands |
POST .../build/ returned 200 {status, message} | 202 with the recipe |
POST .../resetup/ returned 200 {status, recipe_id} | 202 with the recipe |
DELETE returned 204 even when the recipe had not actually been deleted | 500 delete_incomplete when the recipe itself could not be deleted |
| Starting a build or a recreate on a recipe that was never configured failed later, inside the build | 409 recipe_not_configured on the spot |
The extraction-table check answered {ready, sources} | {all_tables_exist, tables} |
last_build_at held the time the configuration last changed | The time the last build started |
datatable_id and error appeared only in the single-recipe response | Both appear in the list as well |
error could be null on a failed recipe | failed always carries an error object |
| An incomplete result looked exactly like a complete one | degraded, not_delivered_reasons and sources[] say what is missing |
existing_recipe_ids came in no particular order | Ordered; the first one is the one to reuse, and the list can be empty |
A recipe belonging to another workspace answered 403 | 404 |
page_size above 100 was silently capped, and a page past the last one answered 404 | Both are 400 invalid_query_parameter |
| A template carried nothing to choose it by | origin, categories and build_mode, and the one-recipe-per-template-per-workspace rule is documented |
output_columns could be null | An empty list |
An account was accepted and returned with a second identifier next to id | accounts[] carries only id; no other account identifier is accepted or returned |
The accounts response carried an item object | It does not |
| The accounts path worked with or without the trailing slash | The trailing slash is mandatory |
A connection from another workspace answered 400 | 404 not_found |
search on accounts also matched the old account key | Lookup by the old key is not supported |
currency was an empty string when the account had none | null |
| The accounts operation documented no paging of its own | 100 accounts per page by default, 100 at most, sorted by id |
Accounts
This is the one place where a straight version swap is not enough. Read it before moving any call that writes a recipe.
For a recipe that is already configured, take the set of accounts from v3.1 itself. Read the
recipe with GET /api/v3.1/automated-recipes/{recipe_id}/,
keep the connections[] block exactly as it comes back, append whatever is new, and send the
result to PUT. The body is the full set, not a
delta, and configuration only ever grows.
Code
Do not rebuild that block from the accounts endpoint. Replacing the ids the recipe already holds is read as removing accounts, and the call is rejected:
Code
For a new recipe, and for accounts you are adding to an existing one, take every id from
GET /api/v3.1/connections/{connection_id}/accounts/
of the same workspace, and use only accounts with is_active: true. Anything else is rejected
with 400 account_unavailable.
The v3 accounts operation is not a substitute here. For some agencies it returns a different key,
and PUT on v3.1 rejects those values with account_unavailable.
If a recipe was already configured with those old keys, contact support with the recipe id and
the x-im-trace-id of a recent request. Do not delete the recipe and deploy it again: deleting a
recipe does not stop the extractions it started, so a fresh recipe would inherit the same data,
and you would have lost the recipe for nothing.
Moving over one call at a time
There is no cut-over moment and no migration request to send.
- Recipes created through v3 are visible in
GET /api/v3.1/automated-recipes/and can be configured, built, recreated and deleted through v3.1 without being recreated. - The two versions read and write the same recipes, so a client can move one operation at a time and keep the rest on v3 while it does.
A workable order:
- Move the read operations first: the template list, the recipe list and the single recipe. Adapt
to the new
statevalues and to the new error shape while nothing is being written. - Move
POSTandPUT, switching the source of account ids at the same time, as described above. - Move
build,resetup,extractionsandDELETE. - Drop the v3 paths from the client.
Two behaviours to unlearn
v3 retried a failed request up to three times on its own, including create, and it could answer with an HTML page or a non-JSON body. v3.1 does neither, so retries are yours to decide and every response body is JSON. See Errors for when a retry is safe.
How long v3 keeps working
The v3 automated recipe operations keep working until they are switched off. We announce the date in advance, so there is no need to move in a hurry.
After the switch-off the v3 recipe paths answer 410 for a while, so a client that has not moved
gets an unmistakable status rather than a silent failure. Later the paths are removed.

