---
title: "Get a recipe"
method: GET
path: "/api/v3.1/automated-recipes/{recipe_id}/"
tags: ["Automated Recipes"]
---

# Get a recipe

`GET /api/v3.1/automated-recipes/{recipe_id}/`

## Request

- Base URL: `https://embedded.improvado.io`
- URL: `https://embedded.improvado.io/api/v3.1/automated-recipes/{recipe_id}/`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `dts_session_id`
- TypeScript: <https://skmtc.dev/improvado/apis/improvado-embedded-api-v3/docs/api/v3.1/automated-recipes/:recipe_id/get.ts> (a function with typed inputs; its response is checked against the schema)

Returns one recipe with the configuration it holds and what the last build did with it. This is the operation to poll after starting a build: repeat it until `state` is `ready_to_work` or `failed`.

`ready_to_work` means built, not built completely. A build runs on the extractions that delivered, so check `degraded` and `sources` as well: `degraded: true` says something was left out, `not_delivered_reasons` says why in one line, and `sources` gives the breakdown per data source. `error` is filled in if and only if `state` is `failed`.

A recipe that was created but never configured comes back with an empty `data_sources`, `last_build_at: null` and `state: extracting_data`. Configure it before you build it.

## Path parameters

- `recipe_id` string, required

## Response `200`

The recipe

- RecipeV31: A single recipe with its configuration and the outcome of its last build. A strict superset of the list item.
  - `recipe_id` string: Recipe identifier. A string, even though it is made of digits.
  - `template_id` integer: The template this recipe was created from.
  - `template_title` string: Current name of that template.
  - `title` string: Recipe name. When you create a recipe without a title, the template supplies the default.
  - `workspace_id` integer: The workspace this recipe lives in.
  - `state` 'extracting_data' | 'building_dependencies' | 'ready_to_work' | 'failed': Where the recipe stands. `extracting_data` - data is being collected; `building_dependencies` - the tables are being built; `ready_to_work` - the last build finished and the output table can be queried; `failed` - the last build failed, see `error`. `ready_to_work` means built, not built completely: it is built from the extractions that delivered, and how complete that is shown by `degraded` and `sources`. New values can be added, so tolerate unknown ones.
  - `degraded` boolean, nullable: Whether the last build was incomplete. Only meaningful while `state` is `ready_to_work`: in every other state, a failed recipe and a running build included, it is `false`. `true` - the build left something out, either a whole data source or some extractions; see `not_delivered_reasons` and `sources`. `false` - everything in the build delivered. `null` - the completeness of the last build is unknown because that build ran before version 3.1.
  - `not_delivered_reasons` string[]: The distinct reasons behind an incomplete last build, sorted and deduplicated across all data sources. Empty when `degraded` is `false` or `null`.
  - `error` RecipeBuildErrorV31, nullable: Why a build failed. On a recipe this is not `null` if and only if `state` is `failed`; on an entry of `sources` it is not `null` if and only if that entry's `status` is `failed`. Build error codes are a namespace of their own, separate from the codes of HTTP error responses - a few names appear in both. The catalogue is on the [Errors](/errors) page.
    - `code` string: Machine-readable build error code, for example `no_data_delivered` or `sql_object_not_found`. Branch on this, never on the message. New codes can be added, so tolerate unknown ones.
    - `message` string: Public human-readable text: a fixed sentence for our own codes, and the cleaned-up message of the database for SQL failures. It never carries raw internal output, and its wording is not part of the contract.
    - `stage` 'extraction' | 'transformation_build' | 'final_build' | 'null', nullable: Which phase of the build failed: `extraction` while data was being collected, `transformation_build` while an intermediate step was built, `final_build` while the output table was built. `null` when the failure was recorded without a phase.
    - `data_source` string, nullable: The data source this failure belongs to, or `null` when it belongs to no single one. Inside `sources` it always matches that entry's `data_source`.
    - `occurred_at` string, date-time, nullable: When the failure was recorded, or `null` when no time was stored with it.
    - `details` object: Extra data for this code, always an object; `{}` for codes that carry none. See [Errors](/errors) for the shape per code.
  - `datatable_id` integer, nullable: The recipe's output data table, or `null` while none is registered. Resolve the physical table name with GET /api/v3/data-tables/{data_table_id} instead of deriving it from a title.
  - `last_build_at` string, date-time, nullable: When the last build of this recipe was started, no matter what started it. `null` means the recipe has never been built. For recipes last built before version 3.1 this is an approximation: the time the recipe record last changed, which is often the end of that build rather than its start.
  - `created_at` string, date-time: When the recipe was created.
  - `updated_at` string, date-time: When the recipe itself last changed. It says nothing about builds - for those use `last_build_at` and `state`.
  - `data_sources` string[]: Data source names the recipe is configured for, sorted. Empty on a recipe that has been created but not configured yet.
  - `allowed_data_sources` string[]: Data source names the template allows, sorted. Everything in `data_sources` has to come from this list.
  - `connections` object[]: The connections and accounts the recipe reads. This is the full set the recipe holds; configuring a recipe always sends the full set, and nothing can be taken away from it.
    - `connection_id` integer: The connection, as numbered in this workspace. The same connector has a different `connection_id` in every workspace.
    - `connection_data_source` string: Data source this connection belongs to, for example `facebook`.
    - `accounts` object[]: The accounts of this connection that the recipe reads.
      - `id` integer: Account identifier, the one the v3.1 connection accounts operation returns.
  - `sync_from_date` string, date: The date the recipe collects data from. Always set in a response, even though it may be omitted from a configuration request.
  - `sources` RecipeSourceV31[]: What the last build did with each configured data source. One entry per name in `data_sources`.
    - `data_source` string: Data source name, for example `facebook`.
    - `status` 'queued' | 'extracting' | 'building' | 'ready' | 'failed' | 'not_built': How this data source ended up in the last build. `queued` - waiting to start; `extracting` - collecting data; `building` - building its tables; `ready` - built; `failed` - it did not build, see `error`; `not_built` - it was not part of the last build, because it was added to the configuration afterwards or because the recipe has never been built. Run a build to include it. New values can be added, so tolerate unknown ones.
    - `error` RecipeBuildErrorV31, nullable: Why a build failed. On a recipe this is not `null` if and only if `state` is `failed`; on an entry of `sources` it is not `null` if and only if that entry's `status` is `failed`. Build error codes are a namespace of their own, separate from the codes of HTTP error responses - a few names appear in both. The catalogue is on the [Errors](/errors) page.
      - `code` string: Machine-readable build error code, for example `no_data_delivered` or `sql_object_not_found`. Branch on this, never on the message. New codes can be added, so tolerate unknown ones.
      - `message` string: Public human-readable text: a fixed sentence for our own codes, and the cleaned-up message of the database for SQL failures. It never carries raw internal output, and its wording is not part of the contract.
      - `stage` 'extraction' | 'transformation_build' | 'final_build' | 'null', nullable: Which phase of the build failed: `extraction` while data was being collected, `transformation_build` while an intermediate step was built, `final_build` while the output table was built. `null` when the failure was recorded without a phase.
      - `data_source` string, nullable: The data source this failure belongs to, or `null` when it belongs to no single one. Inside `sources` it always matches that entry's `data_source`.
      - `occurred_at` string, date-time, nullable: When the failure was recorded, or `null` when no time was stored with it.
      - `details` object: Extra data for this code, always an object; `{}` for codes that carry none. See [Errors](/errors) for the shape per code.
    - `not_delivered_count` integer: How many extractions of this data source did not make it into the last build. This is the full number; `not_delivered` lists at most 100 of them.
    - `not_delivered` object[]: The extractions that did not make it into the last build, ordered by `account_id` and capped at 100 entries per data source. An empty list means everything this data source was waiting for delivered.
      - `extraction_id` integer: The extraction that did not deliver. Look it up in the extractions API of the same workspace.
      - `account_id` integer: The account the extraction belongs to. This is the same `id` you sent in `connections[].accounts[]` when you configured the recipe.
      - `reason` 'connection_unavailable' | 'account_disabled' | 'permission_denied' | 'extraction_failing' | 'report_type_deprecated' | 'paused' | 'not_running' | 'timed_out' | 'unknown': Why it did not deliver. `connection_unavailable` - the connection has to be reconnected; `account_disabled` - the account is switched off; `permission_denied` - access to the account was withdrawn on the platform; `extraction_failing` - the extraction keeps failing on the platform; `report_type_deprecated` - the platform retired this report; `paused` - the extraction is paused; `not_running` - a reused extraction is not running; `timed_out` - it did not deliver within the window the build waits; `unknown` - none of the above. What to do about each is in [Deploying recipes](/recipes). New values can be added, so tolerate unknown ones.

## Other responses

- `400`: The request could not be processed. `bad_request` is the catch-all code for a 4xx that has no code of its own, so the same envelope can arrive with another 4xx status, for example 415.
- `401`: The bearer token is missing, invalid or expired
- `403`: The caller is authenticated but this operation is not available to them
- `404`: No such recipe in this workspace. The same answer covers a recipe of another workspace or agency, a recipe that was deleted and a recipe that is not managed through this API.
- `405`: The HTTP method is not supported on this path
- `500`: Something failed on our side. The request was not served; retry later.
- `503`: Temporarily unavailable. The response carries the header `Retry-After: 30`, so wait 30 seconds and repeat the request.

---

[API](https://skmtc.dev/improvado/apis/improvado-embedded-api-v3.md) - [All operations](https://skmtc.dev/improvado/apis/improvado-embedded-api-v3/llms.txt) - [OpenAPI document](https://skmtc.dev/improvado/apis/improvado-embedded-api-v3/revisions/a881099bd6c4?raw)
