# Recipe catalog: Scarleta API reference

Page: https://www.scarleta.ai/docs/reference/recipe-catalog
Base URL: https://api.scarleta.ai. Authentication: `Authorization: Bearer $SCARLETA_API_KEY`.
Operations: 5.

## GET /v1/recipe/{recipe_id}

Operation id: `get_recipe`

**Get a recipe**

Returns one recipe with its steps. You can read catalog recipes and your own account's recipes. Step feature names are the neutral capability names.

Access: API key required; free and paid accounts. Cost: no token cost.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `recipe_id` | path | string | yes | The recipe id, for example `rec_4821_mix_check`. Ids are case-insensitive and are read in lower case. Allowed: at least 1 character. |

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `success` | true | Always true. |
| `recipe` | object |   |
| `recipe.recipe_id` | string | Identifier of the recipe. |
| `recipe.recipe_name` | string \| null | The recipe name. |
| `recipe.user_intent` | string \| null | What the recipe was made to do, in the words it was created with. |
| `recipe.ai_description` | string \| null | A short description of what the recipe does; null when none was set. |
| `recipe.domain` | string \| null | The subject area of the recipe; null when none was set. |
| `recipe.scope` | string | Who can see the recipe: `universal` (the public catalog), `org-private` (your team) or `user-custom` (you). |
| `recipe.catalog_status` | string \| null | `draft`, `published` or null for a recipe that was saved without a status. |
| `recipe.author_id` | string \| null | Identifier of the author, for catalog recipes; null otherwise. |
| `recipe.author_kind` | string \| null | What kind of author made it, for catalog recipes; null otherwise. |
| `recipe.forked_from` | string \| null | The recipe this one was forked from, or null. |
| `recipe.is_template` | boolean | True for a catalog template recipe. |
| `recipe.usage_count` | integer | How many times the recipe has been run. Allowed: -9007199254740991 to 9007199254740991. |
| `recipe.steps` | array<object> | The ordered steps. Each has a `step` number, a `tool` name and its `parameters`, and may list `features` and `depends_on`. |
| `recipe.budget` | any | The recipe's budget settings, or null. |
| `recipe.execution` | any | The recipe's execution settings, or null. |
| `recipe.is_owner` | boolean | True when your account can delete this recipe. |

### Responses

200: Success

```json
{
  "data": {
    "success": true,
    "recipe": {
      "recipe_id": "rec_1005_cat_spectral",
      "recipe_name": "Analyze the spectral characteristics of an audio recording",
      "user_intent": "analyze the spectral content of this audio",
      "ai_description": "Analyze brightness, spectral centroid, rolloff and energy for mixing and sound-design decisions.",
      "domain": "audio analysis",
      "scope": "universal",
      "catalog_status": "published",
      "author_id": "example-author",
      "author_kind": "scarleta",
      "forked_from": null,
      "is_template": true,
      "usage_count": 8,
      "steps": [
        {
          "step": 1,
          "tool": "spectral_analysis",
          "features": [
            "spectral.centroid",
            "spectral.rolloff"
          ],
          "parameters": {
            "analysis_level": "basic"
          }
        }
      ],
      "budget": null,
      "execution": null,
      "is_owner": false
    }
  },
  "meta": {
    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
  }
}
```

401: Missing, malformed, unknown or revoked API key.

```json
{
  "error": {
    "code": "invalid_key",
    "message": "Invalid or revoked API key",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
  }
}
```

404: No recipe with this id is visible to you: it does not exist, or it is a private recipe of another account. Both are answered the same way.

```json
{
  "error": {
    "code": "not_found",
    "message": "Recipe not found",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
  }
}
```

429: Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.

```json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
  }
}
```

503: Temporary platform condition; retry shortly.

```json
{
  "error": {
    "code": "auth_unavailable",
    "message": "Authentication service temporarily unavailable",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
  }
}
```

### Error codes

[`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_unavailable), [`invalid_auth_format`](https://www.scarleta.ai/docs/errors#invalid_auth_format), [`invalid_key`](https://www.scarleta.ai/docs/errors#invalid_key), [`invalid_key_format`](https://www.scarleta.ai/docs/errors#invalid_key_format), [`missing_api_key`](https://www.scarleta.ai/docs/errors#missing_api_key), [`missing_auth`](https://www.scarleta.ai/docs/errors#missing_auth), [`not_found`](https://www.scarleta.ai/docs/errors#not_found), [`rate_limit_exceeded`](https://www.scarleta.ai/docs/errors#rate_limit_exceeded), [`rate_limit_unavailable`](https://www.scarleta.ai/docs/errors#rate_limit_unavailable), [`unauthorized`](https://www.scarleta.ai/docs/errors#unauthorized)

### Example

```bash
RECIPE_ID="YOUR_RECIPE_ID"
curl "https://api.scarleta.ai/v1/recipe/$RECIPE_ID" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"
```

## GET /v1/recipe/{recipe_id}/comments

Operation id: `list_recipe_comments`

**List the comments on a recipe**

Returns the discussion on a recipe you can see, oldest first. Page with `limit` and `offset`; `has_more` is true when another page exists.

Access: API key required; free and paid accounts. Cost: no token cost.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `recipe_id` | path | string | yes | The recipe id, for example `rec_4821_mix_check`. Ids are case-insensitive and are read in lower case. Allowed: at least 1 character. |
| `limit` | query | integer | no | Comments to return. Defaults to 100; a value above 200 is clamped to 200, a value below 1 is read as 1, and a value that is not a number falls back to the default. |
| `offset` | query | integer | no | Comments to skip. Defaults to 0; a negative or non-numeric value is read as 0. Allowed: 0 to 9007199254740991. |

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `success` | true | Always true. |
| `comments` | array<object> |   |
| `comments[].comment_id` | string | Identifier of the comment. |
| `comments[].recipe_id` | string | The recipe the comment belongs to. |
| `comments[].author_label` | string | A stable display name for the author, such as `Member 11e594`. It cannot be turned back into an account id. |
| `comments[].body` | string | The comment text. |
| `comments[].created_at` | integer | When the comment was posted, in milliseconds since the Unix epoch. Allowed: -9007199254740991 to 9007199254740991. |
| `count` | integer | Comments in `comments`. Allowed: -9007199254740991 to 9007199254740991. |
| `has_more` | boolean | True when more comments exist after this page. |

### Responses

200: Success

```json
{
  "data": {
    "success": true,
    "comments": [
      {
        "comment_id": "cmt_0b2d9f4e-6a31-4c58-9e07-3d1a5b7c9e02",
        "recipe_id": "rec_4821_mix_check",
        "author_label": "Member 11e594",
        "body": "The tempo step works well on this track.",
        "created_at": 1792554097272
      }
    ],
    "count": 1,
    "has_more": false
  },
  "meta": {
    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
  }
}
```

401: Missing, malformed, unknown or revoked API key.

```json
{
  "error": {
    "code": "invalid_key",
    "message": "Invalid or revoked API key",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
  }
}
```

404: No recipe with this id is visible to you: it does not exist, or it is a private recipe of another account. Both are answered the same way.

```json
{
  "error": {
    "code": "not_found",
    "message": "Recipe not found",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
  }
}
```

429: Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.

```json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
  }
}
```

503: Temporary platform condition; retry shortly.

```json
{
  "error": {
    "code": "auth_unavailable",
    "message": "Authentication service temporarily unavailable",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
  }
}
```

### Error codes

[`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_unavailable), [`invalid_auth_format`](https://www.scarleta.ai/docs/errors#invalid_auth_format), [`invalid_key`](https://www.scarleta.ai/docs/errors#invalid_key), [`invalid_key_format`](https://www.scarleta.ai/docs/errors#invalid_key_format), [`missing_api_key`](https://www.scarleta.ai/docs/errors#missing_api_key), [`missing_auth`](https://www.scarleta.ai/docs/errors#missing_auth), [`not_found`](https://www.scarleta.ai/docs/errors#not_found), [`rate_limit_exceeded`](https://www.scarleta.ai/docs/errors#rate_limit_exceeded), [`rate_limit_unavailable`](https://www.scarleta.ai/docs/errors#rate_limit_unavailable), [`unauthorized`](https://www.scarleta.ai/docs/errors#unauthorized)

### Example

```bash
RECIPE_ID="YOUR_RECIPE_ID"
curl "https://api.scarleta.ai/v1/recipe/$RECIPE_ID/comments" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"
```

## POST /v1/recipe/{recipe_id}/comments

Operation id: `post_recipe_comment`

**Post a comment on a recipe**

Adds a comment to a recipe you can see and returns it with `201`. The comment is shown under a display name derived from your account, never the account id. There is no route to edit or delete a comment; comments on a recipe are removed when the recipe is deleted. A body that is not valid JSON is answered like an empty comment: `400 invalid_request`.

Access: API key required; free and paid accounts. Cost: no token cost.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `recipe_id` | path | string | yes | The recipe id, for example `rec_4821_mix_check`. Ids are case-insensitive and are read in lower case. Allowed: at least 1 character. |

### Request body

| Field | Type | Description |
| --- | --- | --- |
| `body` | string | The comment text, at most 4000 characters after leading and trailing spaces are removed. Required, and not blank. Allowed: 1 to 4000 characters. |

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `success` | true | Always true. |
| `comment` | object |   |
| `comment.comment_id` | string | Identifier of the comment. |
| `comment.recipe_id` | string | The recipe the comment belongs to. |
| `comment.author_label` | string | A stable display name for the author, such as `Member 11e594`. It cannot be turned back into an account id. |
| `comment.body` | string | The comment text. |
| `comment.created_at` | integer | When the comment was posted, in milliseconds since the Unix epoch. Allowed: -9007199254740991 to 9007199254740991. |

### Responses

201: The comment just posted.

```json
{
  "data": {
    "success": true,
    "comment": {
      "comment_id": "cmt_0b2d9f4e-6a31-4c58-9e07-3d1a5b7c9e02",
      "recipe_id": "rec_4821_mix_check",
      "author_label": "Member 11e594",
      "body": "The tempo step works well on this track.",
      "created_at": 1792554097272
    }
  },
  "meta": {
    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
  }
}
```

400: The comment is missing or blank, is over the length limit, or the body is not valid JSON.

```json
{
  "error": {
    "code": "invalid_request",
    "message": "Comment body is required",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_request"
  }
}
```

401: Missing, malformed, unknown or revoked API key.

```json
{
  "error": {
    "code": "invalid_key",
    "message": "Invalid or revoked API key",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
  }
}
```

404: No recipe with this id is visible to you: it does not exist, or it is a private recipe of another account. Both are answered the same way.

```json
{
  "error": {
    "code": "not_found",
    "message": "Recipe not found",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
  }
}
```

429: Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.

```json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
  }
}
```

503: Temporary platform condition; retry shortly.

```json
{
  "error": {
    "code": "auth_unavailable",
    "message": "Authentication service temporarily unavailable",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
  }
}
```

### Error codes

[`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_unavailable), [`invalid_auth_format`](https://www.scarleta.ai/docs/errors#invalid_auth_format), [`invalid_key`](https://www.scarleta.ai/docs/errors#invalid_key), [`invalid_key_format`](https://www.scarleta.ai/docs/errors#invalid_key_format), [`invalid_request`](https://www.scarleta.ai/docs/errors#invalid_request), [`missing_api_key`](https://www.scarleta.ai/docs/errors#missing_api_key), [`missing_auth`](https://www.scarleta.ai/docs/errors#missing_auth), [`not_found`](https://www.scarleta.ai/docs/errors#not_found), [`rate_limit_exceeded`](https://www.scarleta.ai/docs/errors#rate_limit_exceeded), [`rate_limit_unavailable`](https://www.scarleta.ai/docs/errors#rate_limit_unavailable), [`unauthorized`](https://www.scarleta.ai/docs/errors#unauthorized)

### Example

```bash
RECIPE_ID="YOUR_RECIPE_ID"
curl -X POST "https://api.scarleta.ai/v1/recipe/$RECIPE_ID/comments" \
  -H "Authorization: Bearer $SCARLETA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "The tempo step works well on this track."
  }'
```

## GET /v1/recipe/author/{author_id}

Operation id: `get_recipe_author`

**Get an author's published recipes**

Returns the public profile of a catalog author: the kind of author, their total number of published catalog recipes, and up to 100 of those recipes, newest first. Page past the first 100 with `offset`. Drafts and private recipes are never listed. The `author_id` of a catalog recipe is on `GET /v1/recipe/{recipe_id}`.

Access: API key required; free and paid accounts. Cost: no token cost.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `author_id` | path | string | yes | The author id, for example `example-author`. Allowed: at least 1 character. |
| `offset` | query | integer | no | Recipes to skip, newest first, to reach the ones after the first 100. Defaults to 0; a negative or non-numeric value is read as 0. A page past the end returns an empty `recipes` list with the real `total`. Allowed: 0 to 9007199254740991. |

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `success` | true | Always true. |
| `author` | object |   |
| `author.author_id` | string | The author id you asked for. |
| `author.author_kind` | string \| null | What kind of author this is. |
| `author.recipes` | array<object> | Their newest published catalog recipes (at most 100). |
| `author.recipes[].recipe_id` | string | Identifier of the recipe. |
| `author.recipes[].recipe_name` | string \| null | The recipe name. |
| `author.recipes[].ai_description` | string \| null | A short description of what the recipe does; null for a recipe that has none. |
| `author.recipes[].domain` | string \| null | The subject area of the recipe, for example `transcription`; null when none was set. |
| `author.total` | integer | How many published catalog recipes the author has in all, which can be more than the 100 listed. Allowed: -9007199254740991 to 9007199254740991. |

### Responses

200: Success

```json
{
  "data": {
    "success": true,
    "author": {
      "author_id": "example-author",
      "author_kind": "scarleta",
      "recipes": [
        {
          "recipe_id": "rec_1005_cat_spectral",
          "recipe_name": "Analyze the spectral characteristics of an audio recording",
          "ai_description": "Analyze brightness, spectral centroid, rolloff and energy for mixing and sound-design decisions.",
          "domain": "audio analysis"
        }
      ],
      "total": 1
    }
  },
  "meta": {
    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
  }
}
```

401: Missing, malformed, unknown or revoked API key.

```json
{
  "error": {
    "code": "invalid_key",
    "message": "Invalid or revoked API key",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
  }
}
```

404: No author with this id has a published catalog recipe.

```json
{
  "error": {
    "code": "not_found",
    "message": "Author not found",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
  }
}
```

429: Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.

```json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
  }
}
```

503: Temporary platform condition; retry shortly.

```json
{
  "error": {
    "code": "auth_unavailable",
    "message": "Authentication service temporarily unavailable",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
  }
}
```

### Error codes

[`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_unavailable), [`invalid_auth_format`](https://www.scarleta.ai/docs/errors#invalid_auth_format), [`invalid_key`](https://www.scarleta.ai/docs/errors#invalid_key), [`invalid_key_format`](https://www.scarleta.ai/docs/errors#invalid_key_format), [`missing_api_key`](https://www.scarleta.ai/docs/errors#missing_api_key), [`missing_auth`](https://www.scarleta.ai/docs/errors#missing_auth), [`not_found`](https://www.scarleta.ai/docs/errors#not_found), [`rate_limit_exceeded`](https://www.scarleta.ai/docs/errors#rate_limit_exceeded), [`rate_limit_unavailable`](https://www.scarleta.ai/docs/errors#rate_limit_unavailable), [`unauthorized`](https://www.scarleta.ai/docs/errors#unauthorized)

### Example

```bash
AUTHOR_ID="YOUR_AUTHOR_ID"
curl "https://api.scarleta.ai/v1/recipe/author/$AUTHOR_ID" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"
```

## GET /v1/recipe/browse

Operation id: `browse_recipes`

**Browse recipes**

Returns recipes you can see, newest first within a tab. `scope=universal` (the default) lists the public catalog; `scope=own` lists recipes saved by your account; `scope=draft` lists your unpublished recipes. Any other `scope` value is read as `universal`, and your own tabs never show another account's recipes. This is a summary list: use `GET /v1/recipe/{recipe_id}` for the steps. `is_owner` is true for recipes your account can delete. When the catalog is switched off for an environment the answer is an empty list, not an error.

Access: API key required; free and paid accounts. Cost: no token cost.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `scope` | query | "universal" \| "own" \| "draft" | no | Which list to return. Defaults to `universal`. `tab` is accepted as another name for this parameter. |
| `limit` | query | integer | no | Recipes to return. Defaults to 50; a value above 100 is clamped to 100, and a value that is not a positive number falls back to the default. Allowed: 1 to 100. |
| `offset` | query | integer | no | Recipes to skip, for paging. Defaults to 0; a value that is not a positive number is read as 0. Allowed: 0 to 9007199254740991. |

### Response fields (inside `data`)

| Field | Type | Description |
| --- | --- | --- |
| `success` | true | Always true. |
| `recipes` | array<object> |   |
| `recipes[].recipe_id` | string | Identifier of the recipe. |
| `recipes[].recipe_name` | string \| null | The recipe name. |
| `recipes[].ai_description` | string \| null | A short description of what the recipe does; null for a recipe that has none. |
| `recipes[].domain` | string \| null | The subject area of the recipe, for example `transcription`; null when none was set. |
| `recipes[].is_owner` | boolean | True when your account can delete this recipe. |
| `count` | integer | Recipes in `recipes`. Allowed: -9007199254740991 to 9007199254740991. |

### Responses

200: The recipes of the chosen tab.

```json
{
  "data": {
    "success": true,
    "recipes": [
      {
        "recipe_id": "rec_1005_cat_spectral",
        "recipe_name": "Analyze the spectral characteristics of an audio recording",
        "ai_description": "Analyze brightness, spectral centroid, rolloff and energy for mixing and sound-design decisions.",
        "domain": "audio analysis",
        "is_owner": false
      }
    ],
    "count": 1
  },
  "meta": {
    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
  }
}
```

401: Missing, malformed, unknown or revoked API key.

```json
{
  "error": {
    "code": "invalid_key",
    "message": "Invalid or revoked API key",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
  }
}
```

429: Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.

```json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
  }
}
```

503: Temporary platform condition; retry shortly.

```json
{
  "error": {
    "code": "auth_unavailable",
    "message": "Authentication service temporarily unavailable",
    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
  }
}
```

### Error codes

[`auth_unavailable`](https://www.scarleta.ai/docs/errors#auth_unavailable), [`invalid_auth_format`](https://www.scarleta.ai/docs/errors#invalid_auth_format), [`invalid_key`](https://www.scarleta.ai/docs/errors#invalid_key), [`invalid_key_format`](https://www.scarleta.ai/docs/errors#invalid_key_format), [`missing_api_key`](https://www.scarleta.ai/docs/errors#missing_api_key), [`missing_auth`](https://www.scarleta.ai/docs/errors#missing_auth), [`rate_limit_exceeded`](https://www.scarleta.ai/docs/errors#rate_limit_exceeded), [`rate_limit_unavailable`](https://www.scarleta.ai/docs/errors#rate_limit_unavailable), [`unauthorized`](https://www.scarleta.ai/docs/errors#unauthorized)

### Example

```bash
curl "https://api.scarleta.ai/v1/recipe/browse" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"
```
