{
  "openapi": "3.1.0",
  "info": {
    "title": "NorReach API",
    "version": "1.0.0",
    "description": "Control your NorReach workspace from your own systems. Every request uses an API key from Settings › API & webhooks and acts as the person who created it, within the key's scopes and that person's role."
  },
  "externalDocs": {
    "description": "The NorReach developer docs",
    "url": "https://docs.norreach.app/"
  },
  "servers": [
    {
      "url": "https://api.norreach.app/v1"
    }
  ],
  "tags": [
    {
      "name": "Ads"
    },
    {
      "name": "Analytics"
    },
    {
      "name": "Approvals"
    },
    {
      "name": "Audit log"
    },
    {
      "name": "Automations"
    },
    {
      "name": "Calls"
    },
    {
      "name": "Campaigns"
    },
    {
      "name": "Contacts"
    },
    {
      "name": "Credits"
    },
    {
      "name": "Deals"
    },
    {
      "name": "Do-not-contact"
    },
    {
      "name": "Inbox"
    },
    {
      "name": "Landing pages"
    },
    {
      "name": "Lists"
    },
    {
      "name": "Meetings"
    },
    {
      "name": "Nora"
    },
    {
      "name": "Phone numbers"
    },
    {
      "name": "Plans"
    },
    {
      "name": "Social"
    },
    {
      "name": "Team"
    },
    {
      "name": "Templates"
    },
    {
      "name": "Webhooks"
    },
    {
      "name": "Workspace"
    }
  ],
  "paths": {
    "/ad-accounts": {
      "get": {
        "operationId": "list_ad_accounts",
        "summary": "List ad accounts",
        "description": "The ad accounts connected to the workspace, per network: name, currency (every amount on the account is in it), time zone, sync state and whether Nora's launches can be published to it from NorReach now. A Meta account's spending limit: GET / PUT /ad-accounts/{id}/spending-limit. Connecting accounts and billing are managed in the app and in the ad network — never through the API.\n\nRequires the `ads:read` scope.",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "network",
            "in": "query",
            "required": false,
            "description": "meta, tiktok, reddit or chatgpt.",
            "schema": {
              "type": "string",
              "enum": [
                "meta",
                "tiktok",
                "reddit",
                "chatgpt"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List ad accounts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "ad_account"
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "meta",
                              "tiktok",
                              "reddit",
                              "chatgpt"
                            ]
                          },
                          "network_name": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "account_number": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The ad network's own number for the account, as the app shows it."
                          },
                          "currency": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "ISO-4217; every amount on this account is in it."
                          },
                          "timezone": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "syncing",
                              "error"
                            ]
                          },
                          "is_default": {
                            "type": "boolean"
                          },
                          "can_publish": {
                            "type": "boolean",
                            "description": "Nora's launches can be published to this account from NorReach right now."
                          },
                          "last_synced_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sync_problem": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "A plain sentence when the last sync failed."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "network",
                          "network_name",
                          "name",
                          "account_number",
                          "currency",
                          "timezone",
                          "status",
                          "is_default",
                          "can_publish",
                          "last_synced_at",
                          "sync_problem"
                        ],
                        "additionalProperties": false,
                        "description": "A connected ad account. Connecting, limits and billing are managed in the app and in the ad network."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
                      "object": "ad_account",
                      "network": "meta",
                      "network_name": "Meta",
                      "name": "Example Care",
                      "account_number": "act_1234567890",
                      "currency": "SEK",
                      "timezone": "Europe/Stockholm",
                      "status": "active",
                      "is_default": true,
                      "can_publish": true,
                      "last_synced_at": "2026-11-05T09:15:02.000Z",
                      "sync_problem": null
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/ad-accounts/{id}/spending-limit": {
      "get": {
        "operationId": "get_ad_account_spending_limit",
        "summary": "An ad account's spending limit",
        "description": "The ad account's own spending limit and the spend counted against it since the last reset, read live from the network, in minor units of the account's currency. At the limit the network stops every ad in the account. Meta accounts; other networks answer 422 ad_network_unsupported.\n\nRequires the `ads:read` scope.",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "An ad account's spending limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "ad_account_spending_limit"
                    },
                    "ad_account_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "network": {
                      "type": "string",
                      "enum": [
                        "meta",
                        "tiktok",
                        "reddit",
                        "chatgpt"
                      ]
                    },
                    "currency": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "limit": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "amount_minor": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Integer minor units (öre, cents)."
                            },
                            "currency": {
                              "type": "string",
                              "minLength": 3,
                              "maxLength": 3,
                              "description": "ISO-4217 code."
                            }
                          },
                          "required": [
                            "amount_minor",
                            "currency"
                          ],
                          "additionalProperties": false,
                          "description": "Money in integer minor units of the ad account's currency."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Null = no account spending limit."
                    },
                    "spent": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "amount_minor": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Integer minor units (öre, cents)."
                            },
                            "currency": {
                              "type": "string",
                              "minLength": 3,
                              "maxLength": 3,
                              "description": "ISO-4217 code."
                            }
                          },
                          "required": [
                            "amount_minor",
                            "currency"
                          ],
                          "additionalProperties": false,
                          "description": "Money in integer minor units of the ad account's currency."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Spend counted against the limit since it was last reset."
                    },
                    "level": {
                      "type": "string",
                      "enum": [
                        "none",
                        "ok",
                        "near",
                        "reached",
                        "unknown"
                      ],
                      "description": "`near` from 80 % of the limit; at `reached` the network stops every ad in the account."
                    }
                  },
                  "required": [
                    "object",
                    "ad_account_id",
                    "network",
                    "currency",
                    "limit",
                    "spent",
                    "level"
                  ],
                  "additionalProperties": false,
                  "description": "The ad account's own spending limit, read live from the network."
                },
                "example": {
                  "object": "ad_account_spending_limit",
                  "ad_account_id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
                  "network": "meta",
                  "currency": "SEK",
                  "limit": {
                    "amount_minor": 5000000,
                    "currency": "SEK"
                  },
                  "spent": {
                    "amount_minor": 1254000,
                    "currency": "SEK"
                  },
                  "level": "ok"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`ad_network_unsupported` — This can't be done on this ad network from NorReach yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:read",
        "x-norreach-action": null,
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "put": {
        "operationId": "set_ad_account_spending_limit",
        "summary": "Set or remove an ad account's spending limit",
        "description": "Sets the ad account's spending limit (`limit` in integer minor units of the account's currency, 1 to 10,000,000 in major units) or removes it (`limit: null` — ads then spend up to their own budgets). The same core as Channels › Ad account's spending controls: owners and admins only (the ads:limits scope), a currency the network's table lists — never a guessed scale. Meta accounts; other networks answer 422 ad_network_unsupported. `dry_run=true` checks it and changes nothing.\n\nRequires the `ads:limits` scope (reaches people, spends or publishes).",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:limits"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "limit": {
                    "anyOf": [
                      {
                        "type": "object",
                        "properties": {
                          "amount_minor": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "Integer minor units (öre, cents)."
                          },
                          "currency": {
                            "type": "string",
                            "minLength": 3,
                            "maxLength": 3,
                            "description": "ISO-4217 code."
                          }
                        },
                        "required": [
                          "amount_minor",
                          "currency"
                        ],
                        "additionalProperties": false,
                        "description": "Money in integer minor units of the ad account's currency."
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Integer minor units in the ad account's currency (1 to 10,000,000 in major units), or null to remove the limit."
                  }
                },
                "required": [
                  "limit"
                ],
                "additionalProperties": false
              },
              "example": {
                "limit": {
                  "amount_minor": 5000000,
                  "currency": "SEK"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Set or remove an ad account's spending limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "ad_account_spending_limit_action"
                    },
                    "ad_account_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "set",
                        "remove",
                        "reset"
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "note": {
                      "type": "string"
                    },
                    "spending_limit": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "object": {
                              "type": "string",
                              "const": "ad_account_spending_limit"
                            },
                            "ad_account_id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            "network": {
                              "type": "string",
                              "enum": [
                                "meta",
                                "tiktok",
                                "reddit",
                                "chatgpt"
                              ]
                            },
                            "currency": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "limit": {
                              "anyOf": [
                                {
                                  "type": "object",
                                  "properties": {
                                    "amount_minor": {
                                      "type": "integer",
                                      "minimum": -9007199254740991,
                                      "maximum": 9007199254740991,
                                      "description": "Integer minor units (öre, cents)."
                                    },
                                    "currency": {
                                      "type": "string",
                                      "minLength": 3,
                                      "maxLength": 3,
                                      "description": "ISO-4217 code."
                                    }
                                  },
                                  "required": [
                                    "amount_minor",
                                    "currency"
                                  ],
                                  "additionalProperties": false,
                                  "description": "Money in integer minor units of the ad account's currency."
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Null = no account spending limit."
                            },
                            "spent": {
                              "anyOf": [
                                {
                                  "type": "object",
                                  "properties": {
                                    "amount_minor": {
                                      "type": "integer",
                                      "minimum": -9007199254740991,
                                      "maximum": 9007199254740991,
                                      "description": "Integer minor units (öre, cents)."
                                    },
                                    "currency": {
                                      "type": "string",
                                      "minLength": 3,
                                      "maxLength": 3,
                                      "description": "ISO-4217 code."
                                    }
                                  },
                                  "required": [
                                    "amount_minor",
                                    "currency"
                                  ],
                                  "additionalProperties": false,
                                  "description": "Money in integer minor units of the ad account's currency."
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Spend counted against the limit since it was last reset."
                            },
                            "level": {
                              "type": "string",
                              "enum": [
                                "none",
                                "ok",
                                "near",
                                "reached",
                                "unknown"
                              ],
                              "description": "`near` from 80 % of the limit; at `reached` the network stops every ad in the account."
                            }
                          },
                          "required": [
                            "object",
                            "ad_account_id",
                            "network",
                            "currency",
                            "limit",
                            "spent",
                            "level"
                          ],
                          "additionalProperties": false,
                          "description": "The ad account's own spending limit, read live from the network."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "ad_account_id",
                    "action",
                    "dry_run",
                    "note",
                    "spending_limit"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "ad_account_spending_limit_action",
                  "ad_account_id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
                  "action": "set",
                  "dry_run": false,
                  "note": "Spending limit set to 50,000 SEK. Meta stops every ad in the account when it's reached.",
                  "spending_limit": {
                    "object": "ad_account_spending_limit",
                    "ad_account_id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
                    "network": "meta",
                    "currency": "SEK",
                    "limit": {
                      "amount_minor": 5000000,
                      "currency": "SEK"
                    },
                    "spent": {
                      "amount_minor": 1254000,
                      "currency": "SEK"
                    },
                    "level": "ok"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request. · `ad_network_unsupported` — This can't be done on this ad network from NorReach yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:limits",
        "x-norreach-action": "ads.limits",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/ad-accounts/{id}/spending-limit/reset": {
      "post": {
        "operationId": "reset_ad_account_spend",
        "summary": "Start a new spending-limit period",
        "description": "Sets the spend counted against the ad account's spending limit back to 0 — ads that stopped at the limit can spend again, up to it. Owners and admins only (ads:limits). Meta accounts; other networks answer 422 ad_network_unsupported. `dry_run=true` checks it and changes nothing.\n\nRequires the `ads:limits` scope (reaches people, spends or publishes).",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:limits"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Start a new spending-limit period",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "ad_account_spending_limit_action"
                    },
                    "ad_account_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "set",
                        "remove",
                        "reset"
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "note": {
                      "type": "string"
                    },
                    "spending_limit": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "object": {
                              "type": "string",
                              "const": "ad_account_spending_limit"
                            },
                            "ad_account_id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            "network": {
                              "type": "string",
                              "enum": [
                                "meta",
                                "tiktok",
                                "reddit",
                                "chatgpt"
                              ]
                            },
                            "currency": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "limit": {
                              "anyOf": [
                                {
                                  "type": "object",
                                  "properties": {
                                    "amount_minor": {
                                      "type": "integer",
                                      "minimum": -9007199254740991,
                                      "maximum": 9007199254740991,
                                      "description": "Integer minor units (öre, cents)."
                                    },
                                    "currency": {
                                      "type": "string",
                                      "minLength": 3,
                                      "maxLength": 3,
                                      "description": "ISO-4217 code."
                                    }
                                  },
                                  "required": [
                                    "amount_minor",
                                    "currency"
                                  ],
                                  "additionalProperties": false,
                                  "description": "Money in integer minor units of the ad account's currency."
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Null = no account spending limit."
                            },
                            "spent": {
                              "anyOf": [
                                {
                                  "type": "object",
                                  "properties": {
                                    "amount_minor": {
                                      "type": "integer",
                                      "minimum": -9007199254740991,
                                      "maximum": 9007199254740991,
                                      "description": "Integer minor units (öre, cents)."
                                    },
                                    "currency": {
                                      "type": "string",
                                      "minLength": 3,
                                      "maxLength": 3,
                                      "description": "ISO-4217 code."
                                    }
                                  },
                                  "required": [
                                    "amount_minor",
                                    "currency"
                                  ],
                                  "additionalProperties": false,
                                  "description": "Money in integer minor units of the ad account's currency."
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Spend counted against the limit since it was last reset."
                            },
                            "level": {
                              "type": "string",
                              "enum": [
                                "none",
                                "ok",
                                "near",
                                "reached",
                                "unknown"
                              ],
                              "description": "`near` from 80 % of the limit; at `reached` the network stops every ad in the account."
                            }
                          },
                          "required": [
                            "object",
                            "ad_account_id",
                            "network",
                            "currency",
                            "limit",
                            "spent",
                            "level"
                          ],
                          "additionalProperties": false,
                          "description": "The ad account's own spending limit, read live from the network."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "ad_account_id",
                    "action",
                    "dry_run",
                    "note",
                    "spending_limit"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "ad_account_spending_limit_action",
                  "ad_account_id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
                  "action": "reset",
                  "dry_run": false,
                  "note": "New period started — spend against the limit is back at 0.",
                  "spending_limit": {
                    "object": "ad_account_spending_limit",
                    "ad_account_id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
                    "network": "meta",
                    "currency": "SEK",
                    "limit": {
                      "amount_minor": 5000000,
                      "currency": "SEK"
                    },
                    "spent": {
                      "amount_minor": 0,
                      "currency": "SEK"
                    },
                    "level": "ok"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request. · `ad_network_unsupported` — This can't be done on this ad network from NorReach yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:limits",
        "x-norreach-action": "ads.limits",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/ad-campaigns": {
      "get": {
        "operationId": "list_ad_campaigns",
        "summary": "List live ad campaigns",
        "description": "The campaigns in the workspace's connected ad accounts as the hourly sync last saw them: network, status (`active`, `paused`, `other`), whether one of Nora's launches made it (`from_norreach`, `launch_id`), its daily budget in minor units when it has one at campaign level, and whether NorReach can switch it on and off (`can_switch` — Meta today). Filter by `network` and `status`. There is no operation that makes, generates or searches ads — new ads come from a plan (POST /briefs), and Nora builds the launch.\n\nRequires the `ads:read` scope.",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "network",
            "in": "query",
            "required": false,
            "description": "meta, tiktok, reddit or chatgpt.",
            "schema": {
              "type": "string",
              "enum": [
                "meta",
                "tiktok",
                "reddit",
                "chatgpt"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "paused",
                "other"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List live ad campaigns",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "ad_campaign"
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "meta",
                              "tiktok",
                              "reddit",
                              "chatgpt"
                            ]
                          },
                          "ad_account_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "paused",
                              "other"
                            ],
                            "description": "`active`, `paused`, or `other` (in review, deleted, archived …)."
                          },
                          "from_norreach": {
                            "type": "boolean",
                            "description": "Made by one of Nora's launches — only these can be switched back on from NorReach (within the plan's daily cap)."
                          },
                          "launch_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "daily_budget": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "amount_minor": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Integer minor units (öre, cents)."
                                  },
                                  "currency": {
                                    "type": "string",
                                    "minLength": 3,
                                    "maxLength": 3,
                                    "description": "ISO-4217 code."
                                  }
                                },
                                "required": [
                                  "amount_minor",
                                  "currency"
                                ],
                                "additionalProperties": false,
                                "description": "Money in integer minor units of the ad account's currency."
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The campaign's daily budget, when it has one at campaign level."
                          },
                          "can_switch": {
                            "type": "boolean",
                            "description": "Pause / resume work from NorReach for this network."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "network",
                          "ad_account_id",
                          "name",
                          "status",
                          "from_norreach",
                          "launch_id",
                          "daily_budget",
                          "can_switch"
                        ],
                        "additionalProperties": false,
                        "description": "A live campaign in a connected ad account, as the hourly sync last saw it."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b",
                      "object": "ad_campaign",
                      "network": "meta",
                      "ad_account_id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
                      "name": "Nurses SE — leads",
                      "status": "active",
                      "from_norreach": true,
                      "launch_id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                      "daily_budget": null,
                      "can_switch": true
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:read",
        "x-norreach-action": null,
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/ad-campaigns/{id}/pause": {
      "post": {
        "operationId": "pause_ad_campaign",
        "summary": "Pause a live ad campaign",
        "description": "Switches a live campaign off in the ad network now — the same core as the Pause button on Ads › Performance. Always allowed for owners, admins and managers, also while outreach is paused: stopping spend is never held back. Campaigns on the other ad networks are paused in the network's own ads manager (422 ad_network_unsupported). `dry_run=true` checks it and changes nothing. Fires ad_campaign.paused.\n\nRequires the `ads:spend` scope (reaches people, spends or publishes).",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:spend"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pause a live ad campaign",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "ad_campaign_action"
                    },
                    "campaign_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "pause",
                        "resume"
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "paused"
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "campaign_id",
                    "action",
                    "dry_run",
                    "status",
                    "changed",
                    "note"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "ad_campaign_action",
                  "campaign_id": "4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b",
                  "action": "pause",
                  "dry_run": false,
                  "status": "paused",
                  "changed": true,
                  "note": "Paused — it stops spending within a few minutes."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request. · `ad_network_unsupported` — This can't be done on this ad network from NorReach yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:spend",
        "x-norreach-action": "ads.spend",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/ad-campaigns/{id}/resume": {
      "post": {
        "operationId": "resume_ad_campaign",
        "summary": "Switch a live ad campaign back on",
        "description": "Switches a paused campaign back on — it starts spending again. Only within the plan's rules: owners, admins and managers; refused while outreach is paused (409 outreach_paused); only a campaign one of Nora's launches made, and only when its daily budget (the campaign's, else its ad sets' together) is within that launch's daily cap (422 ad_switch_blocked with `reason`: not_from_norreach, over_cap, budget_unknown). A campaign made outside NorReach is switched on in the network's own ads manager. Other ad networks than Meta: 422 ad_network_unsupported. Idempotency-Key required; `dry_run=true` runs every check and changes nothing. Fires ad_campaign.resumed.\n\nRequires the `ads:spend` scope (reaches people, spends or publishes).",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:spend"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Switch a live ad campaign back on",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "ad_campaign_action"
                    },
                    "campaign_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "pause",
                        "resume"
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "paused"
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "campaign_id",
                    "action",
                    "dry_run",
                    "status",
                    "changed",
                    "note"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "ad_campaign_action",
                  "campaign_id": "4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b",
                  "action": "resume",
                  "dry_run": false,
                  "status": "active",
                  "changed": true,
                  "note": "Switched on — it spends within its budget again."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request. · `ad_switch_blocked` — This campaign can't be switched back on from NorReach. · `ad_network_unsupported` — This can't be done on this ad network from NorReach yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:spend",
        "x-norreach-action": "ads.spend",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/ad-launches": {
      "get": {
        "operationId": "list_ad_launches",
        "summary": "List ad launches",
        "description": "The ad launches Nora built from the workspace's plans, newest first: network, status (`ready` = waiting for a person's yes), budget in minor units, schedule, how many ad sets and ads publishing creates, and the plan it came from. Filter by `status` and `network`. There is no operation that makes, generates or searches ads — new ads come from a plan (POST /briefs), and Nora builds the launch.\n\nRequires the `ads:read` scope.",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "generating",
                "ready",
                "publishing",
                "published",
                "failed"
              ]
            }
          },
          {
            "name": "network",
            "in": "query",
            "required": false,
            "description": "meta, tiktok, reddit or chatgpt.",
            "schema": {
              "type": "string",
              "enum": [
                "meta",
                "tiktok",
                "reddit",
                "chatgpt"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List ad launches",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "ad_launch"
                          },
                          "name": {
                            "type": "string"
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "meta",
                              "tiktok",
                              "reddit",
                              "chatgpt"
                            ]
                          },
                          "network_name": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "generating",
                              "ready",
                              "publishing",
                              "published",
                              "failed"
                            ],
                            "description": "draft → generating → ready → publishing → published (or failed). Only `ready` waits for a person's yes."
                          },
                          "plan_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The plan whose cards Nora built this launch from."
                          },
                          "ad_account_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "objective": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "landing_url": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "budget": {
                            "type": "object",
                            "properties": {
                              "daily_per_ad_set": {
                                "anyOf": [
                                  {
                                    "type": "object",
                                    "properties": {
                                      "amount_minor": {
                                        "type": "integer",
                                        "minimum": -9007199254740991,
                                        "maximum": 9007199254740991,
                                        "description": "Integer minor units (öre, cents)."
                                      },
                                      "currency": {
                                        "type": "string",
                                        "minLength": 3,
                                        "maxLength": 3,
                                        "description": "ISO-4217 code."
                                      }
                                    },
                                    "required": [
                                      "amount_minor",
                                      "currency"
                                    ],
                                    "additionalProperties": false,
                                    "description": "Money in integer minor units of the ad account's currency."
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "Per ad set (ad group) per day. Editable with PATCH while draft, ready or failed."
                              },
                              "daily_cap": {
                                "anyOf": [
                                  {
                                    "type": "object",
                                    "properties": {
                                      "amount_minor": {
                                        "type": "integer",
                                        "minimum": -9007199254740991,
                                        "maximum": 9007199254740991,
                                        "description": "Integer minor units (öre, cents)."
                                      },
                                      "currency": {
                                        "type": "string",
                                        "minLength": 3,
                                        "maxLength": 3,
                                        "description": "ISO-4217 code."
                                      }
                                    },
                                    "required": [
                                      "amount_minor",
                                      "currency"
                                    ],
                                    "additionalProperties": false,
                                    "description": "Money in integer minor units of the ad account's currency."
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "The most the whole launch may spend per day (set by the plan). A budget above it is refused."
                              },
                              "campaign": {
                                "anyOf": [
                                  {
                                    "type": "object",
                                    "properties": {
                                      "kind": {
                                        "type": "string",
                                        "enum": [
                                          "daily",
                                          "lifetime"
                                        ]
                                      },
                                      "amount": {
                                        "anyOf": [
                                          {
                                            "type": "object",
                                            "properties": {
                                              "amount_minor": {
                                                "type": "integer",
                                                "minimum": -9007199254740991,
                                                "maximum": 9007199254740991,
                                                "description": "Integer minor units (öre, cents)."
                                              },
                                              "currency": {
                                                "type": "string",
                                                "minLength": 3,
                                                "maxLength": 3,
                                                "description": "ISO-4217 code."
                                              }
                                            },
                                            "required": [
                                              "amount_minor",
                                              "currency"
                                            ],
                                            "additionalProperties": false,
                                            "description": "Money in integer minor units of the ad account's currency."
                                          },
                                          {
                                            "type": "null"
                                          }
                                        ]
                                      }
                                    },
                                    "required": [
                                      "kind",
                                      "amount"
                                    ],
                                    "additionalProperties": false
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "A campaign-level budget, on networks that use one."
                              }
                            },
                            "required": [
                              "daily_per_ad_set",
                              "daily_cap",
                              "campaign"
                            ],
                            "additionalProperties": false
                          },
                          "ad_sets": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "How many ad sets (ad groups) publishing creates."
                          },
                          "ads": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "How many ads publishing creates."
                          },
                          "schedule": {
                            "type": "object",
                            "properties": {
                              "mode": {
                                "type": "string",
                                "enum": [
                                  "continuous",
                                  "range"
                                ],
                                "description": "continuous = runs until switched off; range = between start and end."
                              },
                              "start": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "YYYY-MM-DD (range only)."
                              },
                              "end": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "YYYY-MM-DD, or null for no end date."
                              }
                            },
                            "required": [
                              "mode",
                              "start",
                              "end"
                            ],
                            "additionalProperties": false,
                            "description": "When the ads run once switched on."
                          },
                          "published_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "problem": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "A plain sentence when something went wrong (details are in the app)."
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "updated_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "name",
                          "network",
                          "network_name",
                          "status",
                          "plan_id",
                          "ad_account_id",
                          "objective",
                          "landing_url",
                          "budget",
                          "ad_sets",
                          "ads",
                          "schedule",
                          "published_at",
                          "problem",
                          "created_at",
                          "updated_at"
                        ],
                        "additionalProperties": false,
                        "description": "An ad launch Nora built from a plan: what publishing would create, with its budget and schedule. Everything is created paused in the ad network."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                      "object": "ad_launch",
                      "name": "Nurses in Stockholm — lead ads",
                      "network": "meta",
                      "network_name": "Meta",
                      "status": "ready",
                      "plan_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                      "ad_account_id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
                      "objective": "leads",
                      "landing_url": "https://example-care.norreach.dev/nurses",
                      "budget": {
                        "daily_per_ad_set": {
                          "amount_minor": 15000,
                          "currency": "SEK"
                        },
                        "daily_cap": {
                          "amount_minor": 50000,
                          "currency": "SEK"
                        },
                        "campaign": null
                      },
                      "ad_sets": 3,
                      "ads": 6,
                      "schedule": {
                        "mode": "range",
                        "start": "2026-11-10",
                        "end": "2026-11-24"
                      },
                      "published_at": null,
                      "problem": null,
                      "created_at": "2026-11-04T09:12:33.120Z",
                      "updated_at": "2026-11-04T10:02:11.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/ad-launches/{id}": {
      "get": {
        "operationId": "get_ad_launch",
        "summary": "Get an ad launch",
        "description": "One ad launch: its status, budget (minor units), daily cap, schedule, landing page, what publishing creates and, when something went wrong, a plain sentence about it (the details are in the app).\n\nRequires the `ads:read` scope.",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get an ad launch",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "ad_launch"
                    },
                    "name": {
                      "type": "string"
                    },
                    "network": {
                      "type": "string",
                      "enum": [
                        "meta",
                        "tiktok",
                        "reddit",
                        "chatgpt"
                      ]
                    },
                    "network_name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "generating",
                        "ready",
                        "publishing",
                        "published",
                        "failed"
                      ],
                      "description": "draft → generating → ready → publishing → published (or failed). Only `ready` waits for a person's yes."
                    },
                    "plan_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The plan whose cards Nora built this launch from."
                    },
                    "ad_account_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "objective": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "landing_url": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "budget": {
                      "type": "object",
                      "properties": {
                        "daily_per_ad_set": {
                          "anyOf": [
                            {
                              "type": "object",
                              "properties": {
                                "amount_minor": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "Integer minor units (öre, cents)."
                                },
                                "currency": {
                                  "type": "string",
                                  "minLength": 3,
                                  "maxLength": 3,
                                  "description": "ISO-4217 code."
                                }
                              },
                              "required": [
                                "amount_minor",
                                "currency"
                              ],
                              "additionalProperties": false,
                              "description": "Money in integer minor units of the ad account's currency."
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Per ad set (ad group) per day. Editable with PATCH while draft, ready or failed."
                        },
                        "daily_cap": {
                          "anyOf": [
                            {
                              "type": "object",
                              "properties": {
                                "amount_minor": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "Integer minor units (öre, cents)."
                                },
                                "currency": {
                                  "type": "string",
                                  "minLength": 3,
                                  "maxLength": 3,
                                  "description": "ISO-4217 code."
                                }
                              },
                              "required": [
                                "amount_minor",
                                "currency"
                              ],
                              "additionalProperties": false,
                              "description": "Money in integer minor units of the ad account's currency."
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "The most the whole launch may spend per day (set by the plan). A budget above it is refused."
                        },
                        "campaign": {
                          "anyOf": [
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "enum": [
                                    "daily",
                                    "lifetime"
                                  ]
                                },
                                "amount": {
                                  "anyOf": [
                                    {
                                      "type": "object",
                                      "properties": {
                                        "amount_minor": {
                                          "type": "integer",
                                          "minimum": -9007199254740991,
                                          "maximum": 9007199254740991,
                                          "description": "Integer minor units (öre, cents)."
                                        },
                                        "currency": {
                                          "type": "string",
                                          "minLength": 3,
                                          "maxLength": 3,
                                          "description": "ISO-4217 code."
                                        }
                                      },
                                      "required": [
                                        "amount_minor",
                                        "currency"
                                      ],
                                      "additionalProperties": false,
                                      "description": "Money in integer minor units of the ad account's currency."
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                }
                              },
                              "required": [
                                "kind",
                                "amount"
                              ],
                              "additionalProperties": false
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "A campaign-level budget, on networks that use one."
                        }
                      },
                      "required": [
                        "daily_per_ad_set",
                        "daily_cap",
                        "campaign"
                      ],
                      "additionalProperties": false
                    },
                    "ad_sets": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "How many ad sets (ad groups) publishing creates."
                    },
                    "ads": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "How many ads publishing creates."
                    },
                    "schedule": {
                      "type": "object",
                      "properties": {
                        "mode": {
                          "type": "string",
                          "enum": [
                            "continuous",
                            "range"
                          ],
                          "description": "continuous = runs until switched off; range = between start and end."
                        },
                        "start": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "YYYY-MM-DD (range only)."
                        },
                        "end": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "YYYY-MM-DD, or null for no end date."
                        }
                      },
                      "required": [
                        "mode",
                        "start",
                        "end"
                      ],
                      "additionalProperties": false,
                      "description": "When the ads run once switched on."
                    },
                    "published_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "problem": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "A plain sentence when something went wrong (details are in the app)."
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updated_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "network",
                    "network_name",
                    "status",
                    "plan_id",
                    "ad_account_id",
                    "objective",
                    "landing_url",
                    "budget",
                    "ad_sets",
                    "ads",
                    "schedule",
                    "published_at",
                    "problem",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "An ad launch Nora built from a plan: what publishing would create, with its budget and schedule. Everything is created paused in the ad network."
                },
                "example": {
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "object": "ad_launch",
                  "name": "Nurses in Stockholm — lead ads",
                  "network": "meta",
                  "network_name": "Meta",
                  "status": "ready",
                  "plan_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                  "ad_account_id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
                  "objective": "leads",
                  "landing_url": "https://example-care.norreach.dev/nurses",
                  "budget": {
                    "daily_per_ad_set": {
                      "amount_minor": 15000,
                      "currency": "SEK"
                    },
                    "daily_cap": {
                      "amount_minor": 50000,
                      "currency": "SEK"
                    },
                    "campaign": null
                  },
                  "ad_sets": 3,
                  "ads": 6,
                  "schedule": {
                    "mode": "range",
                    "start": "2026-11-10",
                    "end": "2026-11-24"
                  },
                  "published_at": null,
                  "problem": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T10:02:11.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_ad_launch",
        "summary": "Change an ad launch's budget, schedule or name",
        "description": "Changes ONLY the name, the daily budget per ad set (integer minor units in the ad account's currency; the whole launch must stay within its daily cap) and the schedule — through the app's own review save, while the launch is a draft, ready or failed (the name can change any time). Audiences, ads, words and pictures are Nora's: ask for changes in the plan. Budgets and schedules of launches on networks other than Meta publish as Nora prepared them (409). `dry_run=true` answers the launch as it would be and changes nothing. Owners, admins and managers.\n\nRequires the `ads:spend` scope (reaches people, spends or publishes).",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:spend"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "description": "The launch's name in NorReach.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "daily_budget_per_ad_set": {
                    "description": "The daily budget of each ad set, in the ad account's currency. Must keep the whole launch within its daily cap.",
                    "type": "object",
                    "properties": {
                      "amount_minor": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991,
                        "description": "Integer minor units (öre, cents)."
                      },
                      "currency": {
                        "type": "string",
                        "minLength": 3,
                        "maxLength": 3,
                        "description": "ISO-4217 code."
                      }
                    },
                    "required": [
                      "amount_minor",
                      "currency"
                    ],
                    "additionalProperties": false
                  },
                  "schedule": {
                    "description": "continuous, or a range from `start` to `end` (null = no end).",
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "mode": {
                            "type": "string",
                            "const": "continuous"
                          }
                        },
                        "required": [
                          "mode"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "type": "object",
                        "properties": {
                          "mode": {
                            "type": "string",
                            "const": "range"
                          },
                          "start": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                            "description": "YYYY-MM-DD."
                          },
                          "end": {
                            "default": null,
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                                "description": "YYYY-MM-DD."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "mode",
                          "start"
                        ],
                        "additionalProperties": false
                      }
                    ]
                  }
                },
                "additionalProperties": false,
                "description": "Only the name, the per-ad-set daily budget and the schedule can change. Audiences, ads, words and pictures are Nora's — ask for changes in the plan."
              },
              "example": {
                "daily_budget_per_ad_set": {
                  "amount_minor": 12000,
                  "currency": "SEK"
                },
                "schedule": {
                  "mode": "range",
                  "start": "2026-11-10",
                  "end": "2026-11-30"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Change an ad launch's budget, schedule or name",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "ad_launch"
                    },
                    "name": {
                      "type": "string"
                    },
                    "network": {
                      "type": "string",
                      "enum": [
                        "meta",
                        "tiktok",
                        "reddit",
                        "chatgpt"
                      ]
                    },
                    "network_name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "generating",
                        "ready",
                        "publishing",
                        "published",
                        "failed"
                      ],
                      "description": "draft → generating → ready → publishing → published (or failed). Only `ready` waits for a person's yes."
                    },
                    "plan_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The plan whose cards Nora built this launch from."
                    },
                    "ad_account_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "objective": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "landing_url": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "budget": {
                      "type": "object",
                      "properties": {
                        "daily_per_ad_set": {
                          "anyOf": [
                            {
                              "type": "object",
                              "properties": {
                                "amount_minor": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "Integer minor units (öre, cents)."
                                },
                                "currency": {
                                  "type": "string",
                                  "minLength": 3,
                                  "maxLength": 3,
                                  "description": "ISO-4217 code."
                                }
                              },
                              "required": [
                                "amount_minor",
                                "currency"
                              ],
                              "additionalProperties": false,
                              "description": "Money in integer minor units of the ad account's currency."
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Per ad set (ad group) per day. Editable with PATCH while draft, ready or failed."
                        },
                        "daily_cap": {
                          "anyOf": [
                            {
                              "type": "object",
                              "properties": {
                                "amount_minor": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "Integer minor units (öre, cents)."
                                },
                                "currency": {
                                  "type": "string",
                                  "minLength": 3,
                                  "maxLength": 3,
                                  "description": "ISO-4217 code."
                                }
                              },
                              "required": [
                                "amount_minor",
                                "currency"
                              ],
                              "additionalProperties": false,
                              "description": "Money in integer minor units of the ad account's currency."
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "The most the whole launch may spend per day (set by the plan). A budget above it is refused."
                        },
                        "campaign": {
                          "anyOf": [
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "enum": [
                                    "daily",
                                    "lifetime"
                                  ]
                                },
                                "amount": {
                                  "anyOf": [
                                    {
                                      "type": "object",
                                      "properties": {
                                        "amount_minor": {
                                          "type": "integer",
                                          "minimum": -9007199254740991,
                                          "maximum": 9007199254740991,
                                          "description": "Integer minor units (öre, cents)."
                                        },
                                        "currency": {
                                          "type": "string",
                                          "minLength": 3,
                                          "maxLength": 3,
                                          "description": "ISO-4217 code."
                                        }
                                      },
                                      "required": [
                                        "amount_minor",
                                        "currency"
                                      ],
                                      "additionalProperties": false,
                                      "description": "Money in integer minor units of the ad account's currency."
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                }
                              },
                              "required": [
                                "kind",
                                "amount"
                              ],
                              "additionalProperties": false
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "A campaign-level budget, on networks that use one."
                        }
                      },
                      "required": [
                        "daily_per_ad_set",
                        "daily_cap",
                        "campaign"
                      ],
                      "additionalProperties": false
                    },
                    "ad_sets": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "How many ad sets (ad groups) publishing creates."
                    },
                    "ads": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "How many ads publishing creates."
                    },
                    "schedule": {
                      "type": "object",
                      "properties": {
                        "mode": {
                          "type": "string",
                          "enum": [
                            "continuous",
                            "range"
                          ],
                          "description": "continuous = runs until switched off; range = between start and end."
                        },
                        "start": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "YYYY-MM-DD (range only)."
                        },
                        "end": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "YYYY-MM-DD, or null for no end date."
                        }
                      },
                      "required": [
                        "mode",
                        "start",
                        "end"
                      ],
                      "additionalProperties": false,
                      "description": "When the ads run once switched on."
                    },
                    "published_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "problem": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "A plain sentence when something went wrong (details are in the app)."
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updated_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "network",
                    "network_name",
                    "status",
                    "plan_id",
                    "ad_account_id",
                    "objective",
                    "landing_url",
                    "budget",
                    "ad_sets",
                    "ads",
                    "schedule",
                    "published_at",
                    "problem",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "An ad launch Nora built from a plan: what publishing would create, with its budget and schedule. Everything is created paused in the ad network."
                },
                "example": {
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "object": "ad_launch",
                  "name": "Nurses in Stockholm — lead ads",
                  "network": "meta",
                  "network_name": "Meta",
                  "status": "ready",
                  "plan_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                  "ad_account_id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a",
                  "objective": "leads",
                  "landing_url": "https://example-care.norreach.dev/nurses",
                  "budget": {
                    "daily_per_ad_set": {
                      "amount_minor": 12000,
                      "currency": "SEK"
                    },
                    "daily_cap": {
                      "amount_minor": 50000,
                      "currency": "SEK"
                    },
                    "campaign": null
                  },
                  "ad_sets": 3,
                  "ads": 6,
                  "schedule": {
                    "mode": "range",
                    "start": "2026-11-10",
                    "end": "2026-11-30"
                  },
                  "published_at": null,
                  "problem": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T10:02:11.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:spend",
        "x-norreach-action": "ads.spend",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/ad-launches/{id}/discard": {
      "post": {
        "operationId": "discard_ad_launch",
        "summary": "Send an ad launch back to a draft",
        "description": "Says no to a launch that is ready to publish: it goes back to a draft under Ads › Launches and nothing is published. The same deciding core as the Approvals page's Skip, so the key also needs approvals:decide (403 insufficient_scope otherwise). Only a `ready` launch can be discarded (409). `dry_run=true` checks it and changes nothing.\n\nRequires the `ads:spend` scope (reaches people, spends or publishes).",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:spend"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Send an ad launch back to a draft",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "ad_launch_action"
                    },
                    "launch_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "publish",
                        "discard"
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "generating",
                        "ready",
                        "publishing",
                        "published",
                        "failed"
                      ],
                      "description": "The launch's status now (or after it, on a dry run)."
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "launch_id",
                    "action",
                    "dry_run",
                    "status",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "What publishing or discarding a launch did — or, on a dry run, would do."
                },
                "example": {
                  "object": "ad_launch_action",
                  "launch_id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "action": "discard",
                  "dry_run": false,
                  "status": "draft",
                  "note": "Skipped — it stays as a draft under Ads › Launches."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:spend",
        "x-norreach-action": "ads.spend",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/ad-launches/{id}/publish": {
      "post": {
        "operationId": "publish_ad_launch",
        "summary": "Publish an ad launch",
        "description": "Publishes a launch Nora built, as the key's creator — exactly as the app's Publish button: it needs the ads.spend role, outreach must not be paused (409 outreach_paused), the landing page must be live, the network must allow publishing from NorReach, the ad account must be connected and the launch must pass the network's own checks (422 ad_publish_blocked with a `reason`). Everything is created PAUSED in the ad network; nothing spends until it's switched on there. It then publishes in the background — follow it with GET /ad-launches/{id}. `dry_run=true` runs every check and changes nothing.\n\nRequires the `ads:spend` scope (reaches people, spends or publishes).",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:spend"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Publish an ad launch",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "ad_launch_action"
                    },
                    "launch_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "publish",
                        "discard"
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "generating",
                        "ready",
                        "publishing",
                        "published",
                        "failed"
                      ],
                      "description": "The launch's status now (or after it, on a dry run)."
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "launch_id",
                    "action",
                    "dry_run",
                    "status",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "What publishing or discarding a launch did — or, on a dry run, would do."
                },
                "example": {
                  "object": "ad_launch_action",
                  "launch_id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "action": "publish",
                  "dry_run": false,
                  "status": "publishing",
                  "note": "Publishing — Nora is setting it up in the ad account, paused. Nothing spends until it's switched on."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request. · `ad_publish_blocked` — This ad launch can't be published yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:spend",
        "x-norreach-action": "ads.spend",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/ads/insights": {
      "get": {
        "operationId": "get_ad_insights",
        "summary": "Ad results",
        "description": "Spend, impressions, clicks, results, cost per result (CPA), conversion value and ROAS from the hourly syncs — the numbers the Ads › Performance page shows — by `day`, `campaign` or `network`, over `from`–`to` (default the last 30 days, at most 366). Money is integer minor units, one row per currency (amounts in different currencies are never added). Missing numbers are null, never 0; the last day or two may still change.\n\nRequires the `ads:read` scope.",
        "tags": [
          "Ads"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "ads:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day (YYYY-MM-DD, default 29 days before `to`).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day (YYYY-MM-DD, default today).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          },
          {
            "name": "group_by",
            "in": "query",
            "required": false,
            "schema": {
              "default": "day",
              "type": "string",
              "enum": [
                "day",
                "campaign",
                "network"
              ]
            }
          },
          {
            "name": "network",
            "in": "query",
            "required": false,
            "description": "meta, tiktok, reddit or chatgpt.",
            "schema": {
              "type": "string",
              "enum": [
                "meta",
                "tiktok",
                "reddit",
                "chatgpt"
              ]
            }
          },
          {
            "name": "ad_account_id",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ad results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "ad_insights"
                    },
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "group_by": {
                      "type": "string",
                      "enum": [
                        "day",
                        "campaign",
                        "network"
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "const": "ad_insight"
                          },
                          "date": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "YYYY-MM-DD (group_by=day)."
                          },
                          "network": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "meta",
                                  "tiktok",
                                  "reddit",
                                  "chatgpt"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "group_by=network or campaign."
                          },
                          "campaign": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "format": "uuid",
                                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                        "description": "An id (UUID)."
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "name": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "id",
                                  "name"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "group_by=campaign. id is null for a campaign no longer in the ad account."
                          },
                          "currency": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Every amount on the row is in this currency. Rows never add different currencies together."
                          },
                          "spend": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "amount_minor": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Integer minor units (öre, cents)."
                                  },
                                  "currency": {
                                    "type": "string",
                                    "minLength": 3,
                                    "maxLength": 3,
                                    "description": "ISO-4217 code."
                                  }
                                },
                                "required": [
                                  "amount_minor",
                                  "currency"
                                ],
                                "additionalProperties": false,
                                "description": "Money in integer minor units of the ad account's currency."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "impressions": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "clicks": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "results": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The goal conversions the network counted."
                          },
                          "result_type": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "What a result is (Leads, Purchases …)."
                          },
                          "cost_per_result": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "amount_minor": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Integer minor units (öre, cents)."
                                  },
                                  "currency": {
                                    "type": "string",
                                    "minLength": 3,
                                    "maxLength": 3,
                                    "description": "ISO-4217 code."
                                  }
                                },
                                "required": [
                                  "amount_minor",
                                  "currency"
                                ],
                                "additionalProperties": false,
                                "description": "Money in integer minor units of the ad account's currency."
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "CPA: spend ÷ results."
                          },
                          "conversion_value": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "amount_minor": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Integer minor units (öre, cents)."
                                  },
                                  "currency": {
                                    "type": "string",
                                    "minLength": 3,
                                    "maxLength": 3,
                                    "description": "ISO-4217 code."
                                  }
                                },
                                "required": [
                                  "amount_minor",
                                  "currency"
                                ],
                                "additionalProperties": false,
                                "description": "Money in integer minor units of the ad account's currency."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "roas": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Return on ad spend: conversion value ÷ spend."
                          },
                          "ctr": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Click-through rate in percent."
                          }
                        },
                        "required": [
                          "object",
                          "date",
                          "network",
                          "campaign",
                          "currency",
                          "spend",
                          "impressions",
                          "clicks",
                          "results",
                          "result_type",
                          "cost_per_result",
                          "conversion_value",
                          "roas",
                          "ctr"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "totals": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "currency": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "spend": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "amount_minor": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Integer minor units (öre, cents)."
                                  },
                                  "currency": {
                                    "type": "string",
                                    "minLength": 3,
                                    "maxLength": 3,
                                    "description": "ISO-4217 code."
                                  }
                                },
                                "required": [
                                  "amount_minor",
                                  "currency"
                                ],
                                "additionalProperties": false,
                                "description": "Money in integer minor units of the ad account's currency."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "results": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "cost_per_result": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "amount_minor": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Integer minor units (öre, cents)."
                                  },
                                  "currency": {
                                    "type": "string",
                                    "minLength": 3,
                                    "maxLength": 3,
                                    "description": "ISO-4217 code."
                                  }
                                },
                                "required": [
                                  "amount_minor",
                                  "currency"
                                ],
                                "additionalProperties": false,
                                "description": "Money in integer minor units of the ad account's currency."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "conversion_value": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "amount_minor": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Integer minor units (öre, cents)."
                                  },
                                  "currency": {
                                    "type": "string",
                                    "minLength": 3,
                                    "maxLength": 3,
                                    "description": "ISO-4217 code."
                                  }
                                },
                                "required": [
                                  "amount_minor",
                                  "currency"
                                ],
                                "additionalProperties": false,
                                "description": "Money in integer minor units of the ad account's currency."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "roas": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "currency",
                          "spend",
                          "results",
                          "cost_per_result",
                          "conversion_value",
                          "roas"
                        ],
                        "additionalProperties": false
                      },
                      "description": "One total per currency."
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "More rows than one answer reads — narrow the range."
                    }
                  },
                  "required": [
                    "object",
                    "from",
                    "to",
                    "group_by",
                    "data",
                    "totals",
                    "truncated"
                  ],
                  "additionalProperties": false,
                  "description": "Ad results from the hourly syncs (the numbers the Ads › Performance page shows). Missing numbers are null, never 0. Days near today may still change."
                },
                "example": {
                  "object": "ad_insights",
                  "from": "2026-10-07",
                  "to": "2026-11-05",
                  "group_by": "network",
                  "data": [
                    {
                      "object": "ad_insight",
                      "date": null,
                      "network": "meta",
                      "campaign": null,
                      "currency": "SEK",
                      "spend": {
                        "amount_minor": 1254000,
                        "currency": "SEK"
                      },
                      "impressions": 182340,
                      "clicks": 2911,
                      "results": 64,
                      "result_type": "Leads",
                      "cost_per_result": {
                        "amount_minor": 19594,
                        "currency": "SEK"
                      },
                      "conversion_value": null,
                      "roas": null,
                      "ctr": 1.5965
                    }
                  ],
                  "totals": [
                    {
                      "currency": "SEK",
                      "spend": {
                        "amount_minor": 1254000,
                        "currency": "SEK"
                      },
                      "results": 64,
                      "cost_per_result": {
                        "amount_minor": 19594,
                        "currency": "SEK"
                      },
                      "conversion_value": null,
                      "roas": null
                    }
                  ],
                  "truncated": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "ads:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/analytics/calls": {
      "get": {
        "operationId": "get_call_analytics",
        "summary": "Get AI call analytics",
        "description": "AI calls: how many, how many reached a person (connect rate), time on the phone, meetings booked on them, outcomes by status, sentiment, how many met their goal, credits used, and calls per day. Optionally for one campaign (`campaign_id`; another workspace's is 404). Over `from`–`to` (YYYY-MM-DD, UTC; default the last 30 days, at most 366 days). Read-only.\n\nRequires the `analytics:read` scope.",
        "tags": [
          "Analytics"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "analytics:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day (YYYY-MM-DD, UTC; default 29 days before `to`).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day (YYYY-MM-DD, UTC; default today).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          },
          {
            "name": "campaign_id",
            "in": "query",
            "required": false,
            "description": "Only this campaign's calls.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get AI call analytics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "call_analytics"
                    },
                    "from": {
                      "type": "string",
                      "description": "First day (YYYY-MM-DD, UTC)."
                    },
                    "to": {
                      "type": "string",
                      "description": "Last day (YYYY-MM-DD, UTC)."
                    },
                    "campaign_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "total": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "connected": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991,
                      "description": "Calls that reached a person."
                    },
                    "connect_rate": {
                      "anyOf": [
                        {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 1
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "0..1 (four decimals); null when there is nothing to divide by."
                    },
                    "total_duration_seconds": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "average_duration_seconds": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Over calls that lasted; null when none did."
                    },
                    "meetings_booked": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991,
                      "description": "Meetings booked on these calls."
                    },
                    "outcomes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "count": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "status",
                          "count"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Calls per status, most first."
                    },
                    "sentiment": {
                      "type": "object",
                      "properties": {
                        "positive": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "neutral": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "negative": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "unknown": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "positive",
                        "neutral",
                        "negative",
                        "unknown"
                      ],
                      "additionalProperties": false
                    },
                    "success": {
                      "type": "object",
                      "properties": {
                        "analyzed": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "successful": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991,
                          "description": "Calls whose goal was met."
                        },
                        "rate": {
                          "anyOf": [
                            {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "0..1 (four decimals); null when there is nothing to divide by."
                        }
                      },
                      "required": [
                        "analyzed",
                        "successful",
                        "rate"
                      ],
                      "additionalProperties": false
                    },
                    "credits_used": {
                      "type": "object",
                      "properties": {
                        "credits": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Whole credits (rounded half away from zero)."
                        },
                        "exact": {
                          "type": "string",
                          "pattern": "^-?\\d+(?:\\.\\d{1,2})?$",
                          "description": "The exact amount as a decimal string — a per-minute charge can hold a fraction of a credit."
                        }
                      },
                      "required": [
                        "credits",
                        "exact"
                      ],
                      "additionalProperties": false,
                      "description": "An amount of credits."
                    },
                    "by_day": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "date": {
                            "type": "string"
                          },
                          "calls": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991
                          },
                          "connected": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "date",
                          "calls",
                          "connected"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "true when a source held more rows than the people / per-day roll-ups read (10 000); the totals are exact counts either way."
                    }
                  },
                  "required": [
                    "object",
                    "from",
                    "to",
                    "campaign_id",
                    "total",
                    "connected",
                    "connect_rate",
                    "total_duration_seconds",
                    "average_duration_seconds",
                    "meetings_booked",
                    "outcomes",
                    "sentiment",
                    "success",
                    "credits_used",
                    "by_day",
                    "truncated"
                  ],
                  "additionalProperties": false,
                  "description": "AI calls over a range: connect rate, duration, outcomes, sentiment, goals met, credits, by day."
                },
                "example": {
                  "object": "call_analytics",
                  "from": "2026-10-07",
                  "to": "2026-11-05",
                  "campaign_id": null,
                  "total": 120,
                  "connected": 46,
                  "connect_rate": 0.3833,
                  "total_duration_seconds": 9120,
                  "average_duration_seconds": 152,
                  "meetings_booked": 9,
                  "outcomes": [
                    {
                      "status": "completed",
                      "count": 41
                    },
                    {
                      "status": "no_answer",
                      "count": 52
                    },
                    {
                      "status": "voicemail",
                      "count": 22
                    },
                    {
                      "status": "transferred",
                      "count": 5
                    }
                  ],
                  "sentiment": {
                    "positive": 21,
                    "neutral": 18,
                    "negative": 7,
                    "unknown": 74
                  },
                  "success": {
                    "analyzed": 46,
                    "successful": 19,
                    "rate": 0.413
                  },
                  "credits_used": {
                    "credits": 1824,
                    "exact": "1824"
                  },
                  "by_day": [
                    {
                      "date": "2026-11-04",
                      "calls": 12,
                      "connected": 5
                    }
                  ],
                  "truncated": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "analytics:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/analytics/campaigns/{id}": {
      "get": {
        "operationId": "get_campaign_analytics",
        "summary": "Get one campaign's analytics",
        "description": "One campaign's (or automation's) numbers: where its contacts stand now (in progress, paused, completed, replied, meeting booked), and its messages sent, delivered, opened, clicked and replied to and its AI calls over the range. Over `from`–`to` (YYYY-MM-DD, UTC; default the last 30 days, at most 366 days). Another workspace's campaign is 404. Read-only.\n\nRequires the `analytics:read` scope.",
        "tags": [
          "Analytics"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "analytics:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day (YYYY-MM-DD, UTC; default 29 days before `to`).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day (YYYY-MM-DD, UTC; default today).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get one campaign's analytics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "campaign_analytics"
                    },
                    "campaign_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "name": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "campaign",
                        "automation"
                      ]
                    },
                    "status": {
                      "type": "string"
                    },
                    "from": {
                      "type": "string",
                      "description": "First day (YYYY-MM-DD, UTC)."
                    },
                    "to": {
                      "type": "string",
                      "description": "Last day (YYYY-MM-DD, UTC)."
                    },
                    "enrollments": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "in_progress": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "paused": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "completed": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "replied": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "meetings_booked": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "total",
                        "in_progress",
                        "paused",
                        "completed",
                        "replied",
                        "meetings_booked"
                      ],
                      "additionalProperties": false,
                      "description": "Where the campaign's contacts stand now (not limited to the range)."
                    },
                    "messages": {
                      "type": "object",
                      "properties": {
                        "sent": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "delivered": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "opened": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "clicked": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "replies": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "sent",
                        "delivered",
                        "opened",
                        "clicked",
                        "replies"
                      ],
                      "additionalProperties": false,
                      "description": "Messages of this campaign in the range."
                    },
                    "calls": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "connected": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "total",
                        "connected"
                      ],
                      "additionalProperties": false,
                      "description": "AI calls of this campaign in the range."
                    }
                  },
                  "required": [
                    "object",
                    "campaign_id",
                    "name",
                    "kind",
                    "status",
                    "from",
                    "to",
                    "enrollments",
                    "messages",
                    "calls"
                  ],
                  "additionalProperties": false,
                  "description": "One campaign's (or automation's) numbers."
                },
                "example": {
                  "object": "campaign_analytics",
                  "campaign_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                  "name": "Clinics — winter staffing",
                  "kind": "campaign",
                  "status": "active",
                  "from": "2026-10-07",
                  "to": "2026-11-05",
                  "enrollments": {
                    "total": 240,
                    "in_progress": 150,
                    "paused": 6,
                    "completed": 60,
                    "replied": 19,
                    "meetings_booked": 5
                  },
                  "messages": {
                    "sent": 610,
                    "delivered": 598,
                    "opened": 0,
                    "clicked": 0,
                    "replies": 22
                  },
                  "calls": {
                    "total": 30,
                    "connected": 11
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "analytics:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/analytics/channels": {
      "get": {
        "operationId": "get_channel_analytics",
        "summary": "Get analytics per channel",
        "description": "Per channel (email, SMS, WhatsApp, LinkedIn): messages sent, replies, the different people reached and who wrote back, and the reply rate (people who replied / people reached). Over `from`–`to` (YYYY-MM-DD, UTC; default the last 30 days, at most 366 days). Read-only.\n\nRequires the `analytics:read` scope.",
        "tags": [
          "Analytics"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "analytics:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day (YYYY-MM-DD, UTC; default 29 days before `to`).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day (YYYY-MM-DD, UTC; default today).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get analytics per channel",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "channel_analytics"
                    },
                    "from": {
                      "type": "string",
                      "description": "First day (YYYY-MM-DD, UTC)."
                    },
                    "to": {
                      "type": "string",
                      "description": "Last day (YYYY-MM-DD, UTC)."
                    },
                    "channels": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "channel": {
                            "type": "string",
                            "enum": [
                              "email",
                              "sms",
                              "whatsapp",
                              "linkedin"
                            ]
                          },
                          "messages_sent": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991,
                            "description": "Messages that went out (queued, sent, delivered, read)."
                          },
                          "replies": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991,
                            "description": "Messages that came in."
                          },
                          "people_reached": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991,
                            "description": "Different people messages went out to."
                          },
                          "people_replied": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991,
                            "description": "Different people who wrote back."
                          },
                          "reply_rate": {
                            "anyOf": [
                              {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "people_replied / people_reached (0..1)."
                          }
                        },
                        "required": [
                          "channel",
                          "messages_sent",
                          "replies",
                          "people_reached",
                          "people_replied",
                          "reply_rate"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "true when a source held more rows than the people / per-day roll-ups read (10 000); the totals are exact counts either way."
                    }
                  },
                  "required": [
                    "object",
                    "from",
                    "to",
                    "channels",
                    "truncated"
                  ],
                  "additionalProperties": false,
                  "description": "Messages, replies and the people reached per channel (email, SMS, WhatsApp, LinkedIn)."
                },
                "example": {
                  "object": "channel_analytics",
                  "from": "2026-10-07",
                  "to": "2026-11-05",
                  "channels": [
                    {
                      "channel": "email",
                      "messages_sent": 1500,
                      "replies": 70,
                      "people_reached": 520,
                      "people_replied": 52,
                      "reply_rate": 0.1
                    },
                    {
                      "channel": "sms",
                      "messages_sent": 210,
                      "replies": 18,
                      "people_reached": 90,
                      "people_replied": 13,
                      "reply_rate": 0.1444
                    },
                    {
                      "channel": "whatsapp",
                      "messages_sent": 80,
                      "replies": 9,
                      "people_reached": 30,
                      "people_replied": 6,
                      "reply_rate": 0.2
                    },
                    {
                      "channel": "linkedin",
                      "messages_sent": 40,
                      "replies": 0,
                      "people_reached": 0,
                      "people_replied": 0,
                      "reply_rate": null
                    }
                  ],
                  "truncated": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "analytics:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/analytics/overview": {
      "get": {
        "operationId": "get_analytics_overview",
        "summary": "Get the analytics overview",
        "description": "The workspace's outreach at a glance: contacts added, messages sent and replies (and the different people behind them), AI calls and how many reached a person, meetings booked, and the campaigns running now. Over `from`–`to` (YYYY-MM-DD, UTC; default the last 30 days, at most 366 days). Read-only.\n\nRequires the `analytics:read` scope.",
        "tags": [
          "Analytics"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "analytics:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day (YYYY-MM-DD, UTC; default 29 days before `to`).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day (YYYY-MM-DD, UTC; default today).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get the analytics overview",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "analytics_overview"
                    },
                    "from": {
                      "type": "string",
                      "description": "First day (YYYY-MM-DD, UTC)."
                    },
                    "to": {
                      "type": "string",
                      "description": "Last day (YYYY-MM-DD, UTC)."
                    },
                    "contacts": {
                      "type": "object",
                      "properties": {
                        "added": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991,
                          "description": "Contacts created in the range."
                        }
                      },
                      "required": [
                        "added"
                      ],
                      "additionalProperties": false
                    },
                    "messages": {
                      "type": "object",
                      "properties": {
                        "sent": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "replies": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "people_reached": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "people_replied": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "reply_rate": {
                          "anyOf": [
                            {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "0..1 (four decimals); null when there is nothing to divide by."
                        }
                      },
                      "required": [
                        "sent",
                        "replies",
                        "people_reached",
                        "people_replied",
                        "reply_rate"
                      ],
                      "additionalProperties": false
                    },
                    "calls": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "connected": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991,
                          "description": "Calls that reached a person."
                        },
                        "connect_rate": {
                          "anyOf": [
                            {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "0..1 (four decimals); null when there is nothing to divide by."
                        }
                      },
                      "required": [
                        "total",
                        "connected",
                        "connect_rate"
                      ],
                      "additionalProperties": false
                    },
                    "meetings": {
                      "type": "object",
                      "properties": {
                        "booked": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991,
                          "description": "Meetings booked in the range (from every source)."
                        }
                      },
                      "required": [
                        "booked"
                      ],
                      "additionalProperties": false
                    },
                    "campaigns": {
                      "type": "object",
                      "properties": {
                        "active": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991,
                          "description": "Campaigns running now."
                        }
                      },
                      "required": [
                        "active"
                      ],
                      "additionalProperties": false
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "true when a source held more rows than the people / per-day roll-ups read (10 000); the totals are exact counts either way."
                    }
                  },
                  "required": [
                    "object",
                    "from",
                    "to",
                    "contacts",
                    "messages",
                    "calls",
                    "meetings",
                    "campaigns",
                    "truncated"
                  ],
                  "additionalProperties": false,
                  "description": "The workspace's outreach over a range: contacts added, messages and replies, AI calls, meetings booked."
                },
                "example": {
                  "object": "analytics_overview",
                  "from": "2026-10-07",
                  "to": "2026-11-05",
                  "contacts": {
                    "added": 214
                  },
                  "messages": {
                    "sent": 1830,
                    "replies": 97,
                    "people_reached": 640,
                    "people_replied": 71,
                    "reply_rate": 0.1109
                  },
                  "calls": {
                    "total": 120,
                    "connected": 46,
                    "connect_rate": 0.3833
                  },
                  "meetings": {
                    "booked": 18
                  },
                  "campaigns": {
                    "active": 4
                  },
                  "truncated": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "analytics:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/approvals": {
      "get": {
        "operationId": "list_approvals",
        "summary": "List what waits for approval",
        "description": "Everything in the workspace waiting for a person's yes — held messages and calls, plan cards, meetings to confirm, ad launches, landing pages — most urgent first, exactly as the Approvals page ranks it. Narrow it with `tab` or `kind`. The queue is a ranked snapshot, not a paged list: `has_more` says items beyond `limit` exist.\n\nRequires the `approvals:read` scope.",
        "tags": [
          "Approvals"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "approvals:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "tab",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "messages",
                "calls",
                "posts",
                "ads",
                "meetings"
              ]
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "run_gate",
                "sequence_send",
                "rule_send",
                "auto_reply",
                "plan_card",
                "meeting",
                "ad_launch",
                "landing_page",
                "api_call",
                "api_message",
                "number_buy"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List what waits for approval",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string",
                            "minLength": 3,
                            "maxLength": 200,
                            "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths)."
                          },
                          "object": {
                            "type": "string",
                            "const": "approval"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "run_gate",
                              "sequence_send",
                              "rule_send",
                              "auto_reply",
                              "plan_card",
                              "meeting",
                              "ad_launch",
                              "landing_page",
                              "api_call",
                              "api_message",
                              "number_buy"
                            ],
                            "description": "What is waiting. `api_call` / `api_message` were requested through this API."
                          },
                          "tab": {
                            "type": "string",
                            "enum": [
                              "messages",
                              "calls",
                              "posts",
                              "ads",
                              "meetings"
                            ]
                          },
                          "title": {
                            "type": "string",
                            "description": "Customer words, e.g. “Follow-up email to Anna Lindqvist”."
                          },
                          "why": {
                            "type": "string",
                            "description": "Why it waits: the rule, the hold, the booking source."
                          },
                          "source_label": {
                            "type": "string",
                            "description": "Where it came from (a campaign, the plan, an automation, the API)."
                          },
                          "contact": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "format": "uuid",
                                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                        "description": "An id (UUID)."
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "name": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "company": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  }
                                },
                                "required": [
                                  "id",
                                  "name",
                                  "company"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "preview": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "kind"
                            ],
                            "additionalProperties": {},
                            "description": "What would go out: an email, a message, a call, a post, an ad, a meeting, a page."
                          },
                          "waiting_since": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "goes_out_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "When it goes out once approved (or by itself, when `auto`)."
                          },
                          "auto": {
                            "type": "boolean",
                            "description": "It goes out at `goes_out_at` by itself unless someone stops it."
                          },
                          "count": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "How many people or rows the item stands for (a batch)."
                          },
                          "risk": {
                            "type": "string",
                            "enum": [
                              "safe",
                              "money",
                              "voice",
                              "external",
                              "unverified_claim"
                            ]
                          },
                          "can": {
                            "type": "object",
                            "properties": {
                              "approve": {
                                "type": "boolean"
                              },
                              "skip": {
                                "type": "boolean"
                              },
                              "redraft": {
                                "type": "boolean",
                                "description": "“Change it in words” works on it."
                              },
                              "edit": {
                                "anyOf": [
                                  {
                                    "type": "string",
                                    "enum": [
                                      "words",
                                      "meeting"
                                    ]
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "What `edits` an approval may carry."
                              },
                              "web_only": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "Set when it can only be decided in the app (e.g. a claim to check)."
                              }
                            },
                            "required": [
                              "approve",
                              "skip",
                              "redraft",
                              "edit",
                              "web_only"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "key",
                          "object",
                          "kind",
                          "tab",
                          "title",
                          "why",
                          "source_label",
                          "contact",
                          "preview",
                          "waiting_since",
                          "goes_out_at",
                          "auto",
                          "count",
                          "risk",
                          "can"
                        ],
                        "additionalProperties": false,
                        "description": "One item waiting for a person's yes."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "key": "plan_card:5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                      "object": "approval",
                      "kind": "plan_card",
                      "tab": "messages",
                      "title": "Follow-up email to Anna Lindqvist",
                      "why": "Your plan asks before it sends follow-ups.",
                      "source_label": "Spring staffing plan",
                      "contact": {
                        "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                        "name": "Anna Lindqvist",
                        "company": "Example Care AB"
                      },
                      "preview": {
                        "kind": "email",
                        "to": "Anna Lindqvist",
                        "subject": "Nurses for the summer",
                        "body": "Hi Anna, …"
                      },
                      "waiting_since": "2026-11-04T09:12:33.120Z",
                      "goes_out_at": "2026-11-05T08:30:00.000Z",
                      "auto": false,
                      "count": 1,
                      "risk": "safe",
                      "can": {
                        "approve": true,
                        "skip": true,
                        "redraft": true,
                        "edit": "words",
                        "web_only": null
                      }
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "approvals:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/approvals/{key}": {
      "get": {
        "operationId": "get_approval",
        "summary": "One waiting item",
        "description": "One item of the queue by its key, with the preview of what would go out. 404 once it has been decided (here, in the app or by Nora).\n\nRequires the `approvals:read` scope.",
        "tags": [
          "Approvals"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "approvals:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths).",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One waiting item",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 200,
                      "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths)."
                    },
                    "object": {
                      "type": "string",
                      "const": "approval"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "run_gate",
                        "sequence_send",
                        "rule_send",
                        "auto_reply",
                        "plan_card",
                        "meeting",
                        "ad_launch",
                        "landing_page",
                        "api_call",
                        "api_message",
                        "number_buy"
                      ],
                      "description": "What is waiting. `api_call` / `api_message` were requested through this API."
                    },
                    "tab": {
                      "type": "string",
                      "enum": [
                        "messages",
                        "calls",
                        "posts",
                        "ads",
                        "meetings"
                      ]
                    },
                    "title": {
                      "type": "string",
                      "description": "Customer words, e.g. “Follow-up email to Anna Lindqvist”."
                    },
                    "why": {
                      "type": "string",
                      "description": "Why it waits: the rule, the hold, the booking source."
                    },
                    "source_label": {
                      "type": "string",
                      "description": "Where it came from (a campaign, the plan, an automation, the API)."
                    },
                    "contact": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                  "description": "An id (UUID)."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "name": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "company": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "id",
                            "name",
                            "company"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "preview": {
                      "type": "object",
                      "properties": {
                        "kind": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "kind"
                      ],
                      "additionalProperties": {},
                      "description": "What would go out: an email, a message, a call, a post, an ad, a meeting, a page."
                    },
                    "waiting_since": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "goes_out_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "When it goes out once approved (or by itself, when `auto`)."
                    },
                    "auto": {
                      "type": "boolean",
                      "description": "It goes out at `goes_out_at` by itself unless someone stops it."
                    },
                    "count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "How many people or rows the item stands for (a batch)."
                    },
                    "risk": {
                      "type": "string",
                      "enum": [
                        "safe",
                        "money",
                        "voice",
                        "external",
                        "unverified_claim"
                      ]
                    },
                    "can": {
                      "type": "object",
                      "properties": {
                        "approve": {
                          "type": "boolean"
                        },
                        "skip": {
                          "type": "boolean"
                        },
                        "redraft": {
                          "type": "boolean",
                          "description": "“Change it in words” works on it."
                        },
                        "edit": {
                          "anyOf": [
                            {
                              "type": "string",
                              "enum": [
                                "words",
                                "meeting"
                              ]
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "What `edits` an approval may carry."
                        },
                        "web_only": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Set when it can only be decided in the app (e.g. a claim to check)."
                        }
                      },
                      "required": [
                        "approve",
                        "skip",
                        "redraft",
                        "edit",
                        "web_only"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "key",
                    "object",
                    "kind",
                    "tab",
                    "title",
                    "why",
                    "source_label",
                    "contact",
                    "preview",
                    "waiting_since",
                    "goes_out_at",
                    "auto",
                    "count",
                    "risk",
                    "can"
                  ],
                  "additionalProperties": false,
                  "description": "One item waiting for a person's yes."
                },
                "example": {
                  "key": "plan_card:5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                  "object": "approval",
                  "kind": "plan_card",
                  "tab": "messages",
                  "title": "Follow-up email to Anna Lindqvist",
                  "why": "Your plan asks before it sends follow-ups.",
                  "source_label": "Spring staffing plan",
                  "contact": {
                    "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                    "name": "Anna Lindqvist",
                    "company": "Example Care AB"
                  },
                  "preview": {
                    "kind": "email",
                    "to": "Anna Lindqvist",
                    "subject": "Nurses for the summer",
                    "body": "Hi Anna, …"
                  },
                  "waiting_since": "2026-11-04T09:12:33.120Z",
                  "goes_out_at": "2026-11-05T08:30:00.000Z",
                  "auto": false,
                  "count": 1,
                  "risk": "safe",
                  "can": {
                    "approve": true,
                    "skip": true,
                    "redraft": true,
                    "edit": "words",
                    "web_only": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "approvals:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/approvals/{key}/approve": {
      "post": {
        "operationId": "approve_approval",
        "summary": "Approve an item",
        "description": "Says yes as the key's creator — it goes out (or goes live) through the same checks as the Approvals page: the outreach pause, the creator's role, the item re-read in this workspace. Optional `edits` change the words (or a meeting's time, length, email or host) as it is approved. An ad launch also needs `ads:spend`, a landing page `pages:publish`, a plan card `plans:approve`. Already decided → 409 already_decided; a claim that needs checking → 409 conflict (decide it in the app). `dry_run=true` checks it still waits and changes nothing.\n\nRequires the `approvals:decide` scope (reaches people, spends or publishes).",
        "tags": [
          "Approvals"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "approvals:decide"
            ]
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths).",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 200
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "edits": {
                    "type": "object",
                    "properties": {
                      "subject": {
                        "type": "string",
                        "maxLength": 300
                      },
                      "body": {
                        "description": "The edited words (email body, message text, a card's words).",
                        "type": "string",
                        "maxLength": 20000
                      },
                      "meeting": {
                        "type": "object",
                        "properties": {
                          "starts_at": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                          },
                          "minutes": {
                            "type": "integer",
                            "minimum": 5,
                            "maximum": 480
                          },
                          "email": {
                            "type": "string",
                            "format": "email",
                            "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                          },
                          "host_id": {
                            "description": "Another member to host it (staff only).",
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "force": {
                            "description": "Approve even though the host's calendar shows a clash.",
                            "type": "boolean"
                          }
                        },
                        "additionalProperties": false
                      }
                    },
                    "additionalProperties": false,
                    "description": "Edits approved together with the item."
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "edits": {
                  "body": "Hi Anna, a shorter version …"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Approve an item",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "object": {
                          "type": "string",
                          "const": "approval_decision"
                        },
                        "key": {
                          "type": "string",
                          "minLength": 3,
                          "maxLength": 200,
                          "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths)."
                        },
                        "decision": {
                          "type": "string",
                          "enum": [
                            "approve",
                            "skip"
                          ]
                        },
                        "status": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "The item's status after the decision (approved, rejected, queued, scheduled …)."
                        },
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "How many rows were decided (a batch: many; 0 when it was already decided the same way)."
                        },
                        "note": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "What happened, in customer words."
                        }
                      },
                      "required": [
                        "object",
                        "key",
                        "decision",
                        "status",
                        "count",
                        "note"
                      ],
                      "additionalProperties": false,
                      "description": "A decision that went through."
                    },
                    {
                      "type": "object",
                      "properties": {
                        "object": {
                          "type": "string",
                          "const": "approval_decision"
                        },
                        "key": {
                          "type": "string",
                          "minLength": 3,
                          "maxLength": 200,
                          "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths)."
                        },
                        "decision": {
                          "type": "string",
                          "enum": [
                            "approve",
                            "skip"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "const": "dry_run"
                        },
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "note": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "would": {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "enum": [
                                "run_gate",
                                "sequence_send",
                                "rule_send",
                                "auto_reply",
                                "plan_card",
                                "meeting",
                                "ad_launch",
                                "landing_page",
                                "api_call",
                                "api_message",
                                "number_buy"
                              ]
                            },
                            "title": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "kind",
                            "title"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "object",
                        "key",
                        "decision",
                        "status",
                        "count",
                        "note",
                        "would"
                      ],
                      "additionalProperties": false
                    }
                  ]
                },
                "example": {
                  "object": "approval_decision",
                  "key": "plan_card:5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                  "decision": "approve",
                  "status": "approved",
                  "count": 1,
                  "note": "Approved — it goes out on schedule."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `already_decided` — Already handled. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again. · `number_cap_reached` — The workspace's limit for buying numbers through the API is reached.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "approvals:decide",
        "x-norreach-action": "approvals.decide",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/approvals/{key}/redraft": {
      "post": {
        "operationId": "redraft_approval",
        "summary": "Change an item in words",
        "description": "Nora rewrites a waiting message or card from a short instruction (“shorter”, “mention the site survey”). Nothing is sent — the item keeps waiting with the new words.\n\nRequires the `approvals:decide` scope (reaches people, spends or publishes).",
        "tags": [
          "Approvals"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "approvals:decide"
            ]
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths).",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 200
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "instruction": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 600
                  }
                },
                "required": [
                  "instruction"
                ],
                "additionalProperties": false
              },
              "example": {
                "instruction": "Shorter, and mention the site survey."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Change an item in words",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "redraft"
                    },
                    "key": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 200,
                      "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths)."
                    },
                    "before": {
                      "type": "object",
                      "properties": {
                        "kind": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "kind"
                      ],
                      "additionalProperties": {}
                    },
                    "preview": {
                      "type": "object",
                      "properties": {
                        "kind": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "kind"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "object",
                    "key",
                    "before",
                    "preview"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "redraft",
                  "key": "plan_card:5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                  "before": {
                    "kind": "email",
                    "to": "Anna Lindqvist",
                    "subject": "Nurses for the summer",
                    "body": "Hi Anna, …"
                  },
                  "preview": {
                    "kind": "email",
                    "to": "Anna Lindqvist",
                    "subject": "Nurses for the summer",
                    "body": "Hi Anna — short version …"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "approvals:decide",
        "x-norreach-action": "approvals.decide",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/approvals/{key}/skip": {
      "post": {
        "operationId": "skip_approval",
        "summary": "Skip an item",
        "description": "Says no: nothing goes out (a meeting is declined and the attendee hears; an ad launch or page goes back to a draft). Already decided → 409 already_decided.\n\nRequires the `approvals:decide` scope (reaches people, spends or publishes).",
        "tags": [
          "Approvals"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "approvals:decide"
            ]
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths).",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 200
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Skip an item",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "object": {
                          "type": "string",
                          "const": "approval_decision"
                        },
                        "key": {
                          "type": "string",
                          "minLength": 3,
                          "maxLength": 200,
                          "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths)."
                        },
                        "decision": {
                          "type": "string",
                          "enum": [
                            "approve",
                            "skip"
                          ]
                        },
                        "status": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "The item's status after the decision (approved, rejected, queued, scheduled …)."
                        },
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "How many rows were decided (a batch: many; 0 when it was already decided the same way)."
                        },
                        "note": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "What happened, in customer words."
                        }
                      },
                      "required": [
                        "object",
                        "key",
                        "decision",
                        "status",
                        "count",
                        "note"
                      ],
                      "additionalProperties": false,
                      "description": "A decision that went through."
                    },
                    {
                      "type": "object",
                      "properties": {
                        "object": {
                          "type": "string",
                          "const": "approval_decision"
                        },
                        "key": {
                          "type": "string",
                          "minLength": 3,
                          "maxLength": 200,
                          "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths)."
                        },
                        "decision": {
                          "type": "string",
                          "enum": [
                            "approve",
                            "skip"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "const": "dry_run"
                        },
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "note": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "would": {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "enum": [
                                "run_gate",
                                "sequence_send",
                                "rule_send",
                                "auto_reply",
                                "plan_card",
                                "meeting",
                                "ad_launch",
                                "landing_page",
                                "api_call",
                                "api_message",
                                "number_buy"
                              ]
                            },
                            "title": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "kind",
                            "title"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "object",
                        "key",
                        "decision",
                        "status",
                        "count",
                        "note",
                        "would"
                      ],
                      "additionalProperties": false
                    }
                  ]
                },
                "example": {
                  "object": "approval_decision",
                  "key": "plan_card:5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                  "decision": "skip",
                  "status": "rejected",
                  "count": 1,
                  "note": "Skipped — nothing is sent."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `already_decided` — Already handled. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again. · `number_cap_reached` — The workspace's limit for buying numbers through the API is reached.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "approvals:decide",
        "x-norreach-action": "approvals.decide",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/approvals/decide": {
      "post": {
        "operationId": "decide_approvals",
        "summary": "Decide several items",
        "description": "Approves or skips up to 50 keys in one request, in order, one result each (`ok`, the status, or the `code` it would have answered alone). Each key goes through the same checks as deciding it alone; an approval of an ad launch, page or plan card without its own scope is refused for that key only.\n\nRequires the `approvals:decide` scope (reaches people, spends or publishes).",
        "tags": [
          "Approvals"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "approvals:decide"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "keys": {
                    "minItems": 1,
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 200,
                      "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths)."
                    }
                  },
                  "decision": {
                    "type": "string",
                    "enum": [
                      "approve",
                      "skip"
                    ]
                  }
                },
                "required": [
                  "keys",
                  "decision"
                ],
                "additionalProperties": false
              },
              "example": {
                "keys": [
                  "plan_card:5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                  "meeting:1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
                ],
                "decision": "approve"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Decide several items",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string",
                            "minLength": 3,
                            "maxLength": 200,
                            "description": "An approval key, e.g. `plan_card:<uuid>`, `meeting:<uuid>`, `rule_send:<uuid>` (URL-encode the colon in paths)."
                          },
                          "ok": {
                            "type": "boolean"
                          },
                          "status": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "count": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "note": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "code": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "When not ok: the problem code it would have answered alone."
                          }
                        },
                        "required": [
                          "key",
                          "ok",
                          "status",
                          "count",
                          "note",
                          "code"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "const": false
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "key": "plan_card:5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                      "ok": true,
                      "status": "approved",
                      "count": 1,
                      "note": "Approved.",
                      "code": null
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "approvals:decide",
        "x-norreach-action": "approvals.decide",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/audit-log": {
      "get": {
        "operationId": "list_audit_log",
        "summary": "List the audit log",
        "description": "The workspace's audit log, newest first: what happened, who did it, and — for anything done through the API — which key (or connected app), from REST or MCP, with the request id. Each entry names the ids it is about; its raw details are never served. Filter by `action` (exact, or a prefix like `contact.*`), `actor` (part of the name, e.g. an email or \"via API key\"), `since` / `until`. Owners and admins.\n\nRequires the `audit:read` scope.",
        "tags": [
          "Audit log"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "audit:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "action",
            "in": "query",
            "required": false,
            "description": "Only this action, or every action under a prefix (`contact.*`).",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_.:-]{1,118}(?:\\.\\*)?$"
            }
          },
          {
            "name": "actor",
            "in": "query",
            "required": false,
            "description": "Only entries whose actor contains this.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "description": "Only entries at or after this time (RFC 3339).",
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "until",
            "in": "query",
            "required": false,
            "description": "Only entries before this time (RFC 3339).",
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List the audit log",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "The entry's id."
                          },
                          "object": {
                            "type": "string",
                            "const": "audit_entry"
                          },
                          "action": {
                            "type": "string",
                            "description": "What happened (contact.erased, api.publish_page, Approved …)."
                          },
                          "actor": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Who did it: a person's email, \"<email> via API key <label> (<prefix>)\", or \"nora\"."
                          },
                          "via": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "kind": {
                                    "type": "string",
                                    "enum": [
                                      "api_key",
                                      "oauth"
                                    ]
                                  },
                                  "surface": {
                                    "type": "string",
                                    "enum": [
                                      "rest",
                                      "mcp"
                                    ],
                                    "description": "REST (/v1) or the MCP server."
                                  },
                                  "key_id": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "format": "uuid",
                                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                        "description": "An id (UUID)."
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "key_prefix": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "client_name": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ],
                                    "description": "The connected app, for OAuth grants."
                                  },
                                  "request_id": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  }
                                },
                                "required": [
                                  "kind",
                                  "surface",
                                  "key_id",
                                  "key_prefix",
                                  "client_name",
                                  "request_id"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Set when it was done through the API: which key, from where."
                          },
                          "targets": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            "description": "The ids it is about (contact_id, campaign_id …)."
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "action",
                          "actor",
                          "via",
                          "targets",
                          "created_at"
                        ],
                        "additionalProperties": false,
                        "description": "One entry of the workspace's audit log. The entry's raw details are never served — only who, what, through which key and the ids it is about."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "48211",
                      "object": "audit_entry",
                      "action": "api.approve_approval",
                      "actor": "anna@example.com via API key CRM sync (nr_live_8fK2pQ1x)",
                      "via": {
                        "kind": "api_key",
                        "surface": "rest",
                        "key_id": "0f1e2d3c-4b5a-4968-8776-655443322110",
                        "key_prefix": "nr_live_8fK2pQ1x",
                        "client_name": null,
                        "request_id": "6f0c2a1e-9b8d-4c7e-a6f5-4e3d2c1b0a99"
                      },
                      "targets": {
                        "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d"
                      },
                      "created_at": "2026-11-05T09:12:33.120Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "audit:read",
        "x-norreach-action": "audit.view",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/automations": {
      "get": {
        "operationId": "list_automations",
        "summary": "List automations",
        "description": "The workspace's automation flows, newest first, a page at a time. Filter by `status` (draft, active, paused, archived = stopped).\n\nRequires the `campaigns:read` scope.",
        "tags": [
          "Automations"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "active",
                "paused",
                "archived"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List automations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "automation"
                          },
                          "name": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "description": "draft, active, paused or archived (stopped)."
                          },
                          "trigger": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "What starts the flow (e.g. manual_contacts, landing_form)."
                          },
                          "node_count": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "compiled_step_count": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "Steps in the program the engine runs (set when it is activated)."
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "name",
                          "status",
                          "trigger",
                          "node_count",
                          "compiled_step_count",
                          "created_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                      "object": "automation",
                      "name": "Webinar follow-up",
                      "status": "draft",
                      "trigger": "manual_contacts",
                      "node_count": 2,
                      "compiled_step_count": 0,
                      "created_at": "2026-11-04T09:12:33.120Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "create_automation",
        "summary": "Save a new automation",
        "description": "Saves a flow (nodes and edges in the automation builder's own format) as a draft. Nothing runs until it is activated; `compile_error` says what would stop that. Every contact, list, segment, AI caller and campaign the flow names must be this workspace's (422 otherwise).\n\nRequires the `campaigns:write` scope.",
        "tags": [
          "Automations"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "flow": {
                    "type": "object",
                    "properties": {
                      "nodes": {
                        "minItems": 1,
                        "maxItems": 200,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 100
                            },
                            "type": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 60
                            },
                            "position": {
                              "type": "object",
                              "properties": {
                                "x": {
                                  "type": "number"
                                },
                                "y": {
                                  "type": "number"
                                }
                              },
                              "required": [
                                "x",
                                "y"
                              ],
                              "additionalProperties": false
                            },
                            "data": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {},
                              "description": "The node: nodeType (trigger, action or condition), triggerType / actionType / conditionType, label and config — the flow builder's own format."
                            }
                          },
                          "required": [
                            "id",
                            "data"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "edges": {
                        "maxItems": 400,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 200
                            },
                            "source": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 100
                            },
                            "target": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 100
                            },
                            "source_handle": {
                              "description": "yes / no on a condition's outgoing edges.",
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 40
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "target_handle": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 40
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "id",
                            "source",
                            "target"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "settings": {
                        "description": "Flow settings (schedule, days, timezone, stopOnReply …).",
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    },
                    "required": [
                      "nodes",
                      "edges"
                    ],
                    "additionalProperties": false,
                    "description": "An automation's flow graph."
                  }
                },
                "required": [
                  "name",
                  "flow"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "Webinar follow-up",
                "flow": {
                  "nodes": [
                    {
                      "id": "start",
                      "type": "trigger",
                      "position": {
                        "x": 0,
                        "y": 0
                      },
                      "data": {
                        "nodeType": "trigger",
                        "triggerType": "manual_contacts",
                        "label": "Picked contacts",
                        "config": {
                          "audience": {
                            "lists": [
                              {
                                "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
                              }
                            ]
                          }
                        }
                      }
                    },
                    {
                      "id": "hello",
                      "type": "action",
                      "position": {
                        "x": 0,
                        "y": 160
                      },
                      "data": {
                        "nodeType": "action",
                        "actionType": "send_email",
                        "label": "Intro email",
                        "config": {
                          "subject": "Nurses for the summer",
                          "template": "Hi {{first_name}}, …"
                        }
                      }
                    }
                  ],
                  "edges": [
                    {
                      "id": "start-hello",
                      "source": "start",
                      "target": "hello",
                      "source_handle": null,
                      "target_handle": null
                    }
                  ],
                  "settings": {
                    "stopOnReply": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Save a new automation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "automation"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "draft, active, paused or archived (stopped)."
                    },
                    "trigger": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "What starts the flow (e.g. manual_contacts, landing_form)."
                    },
                    "node_count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "compiled_step_count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Steps in the program the engine runs (set when it is activated)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "flow": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "nodes": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {}
                              }
                            },
                            "edges": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {}
                              }
                            },
                            "settings": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {}
                            }
                          },
                          "required": [
                            "nodes",
                            "edges",
                            "settings"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "compile_error": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Why the flow can't be activated as it is (null = it compiles)."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "status",
                    "trigger",
                    "node_count",
                    "compiled_step_count",
                    "created_at",
                    "flow",
                    "compile_error"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                  "object": "automation",
                  "name": "Webinar follow-up",
                  "status": "draft",
                  "trigger": "manual_contacts",
                  "node_count": 2,
                  "compiled_step_count": 0,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "flow": {
                    "nodes": [
                      {
                        "id": "start",
                        "type": "trigger",
                        "position": {
                          "x": 0,
                          "y": 0
                        },
                        "data": {
                          "nodeType": "trigger",
                          "triggerType": "manual_contacts",
                          "label": "Picked contacts",
                          "config": {
                            "audience": {
                              "lists": [
                                {
                                  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
                                }
                              ]
                            }
                          }
                        }
                      },
                      {
                        "id": "hello",
                        "type": "action",
                        "position": {
                          "x": 0,
                          "y": 160
                        },
                        "data": {
                          "nodeType": "action",
                          "actionType": "send_email",
                          "label": "Intro email",
                          "config": {
                            "subject": "Nurses for the summer",
                            "template": "Hi {{first_name}}, …"
                          }
                        }
                      }
                    ],
                    "edges": [
                      {
                        "id": "start-hello",
                        "source": "start",
                        "target": "hello",
                        "source_handle": null,
                        "target_handle": null
                      }
                    ],
                    "settings": {
                      "stopOnReply": true,
                      "name": "Webinar follow-up"
                    }
                  },
                  "compile_error": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:write",
        "x-norreach-action": "campaigns.edit",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/automations/{id}": {
      "get": {
        "operationId": "get_automation",
        "summary": "One automation",
        "description": "An automation with its flow graph, the size of the program the engine runs, and `compile_error` (why it can't be activated as it is, or null).\n\nRequires the `campaigns:read` scope.",
        "tags": [
          "Automations"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One automation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "automation"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "draft, active, paused or archived (stopped)."
                    },
                    "trigger": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "What starts the flow (e.g. manual_contacts, landing_form)."
                    },
                    "node_count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "compiled_step_count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Steps in the program the engine runs (set when it is activated)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "flow": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "nodes": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {}
                              }
                            },
                            "edges": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {}
                              }
                            },
                            "settings": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {}
                            }
                          },
                          "required": [
                            "nodes",
                            "edges",
                            "settings"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "compile_error": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Why the flow can't be activated as it is (null = it compiles)."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "status",
                    "trigger",
                    "node_count",
                    "compiled_step_count",
                    "created_at",
                    "flow",
                    "compile_error"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                  "object": "automation",
                  "name": "Webinar follow-up",
                  "status": "draft",
                  "trigger": "manual_contacts",
                  "node_count": 2,
                  "compiled_step_count": 0,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "flow": {
                    "nodes": [
                      {
                        "id": "start",
                        "type": "trigger",
                        "position": {
                          "x": 0,
                          "y": 0
                        },
                        "data": {
                          "nodeType": "trigger",
                          "triggerType": "manual_contacts",
                          "label": "Picked contacts",
                          "config": {
                            "audience": {
                              "lists": [
                                {
                                  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
                                }
                              ]
                            }
                          }
                        }
                      },
                      {
                        "id": "hello",
                        "type": "action",
                        "position": {
                          "x": 0,
                          "y": 160
                        },
                        "data": {
                          "nodeType": "action",
                          "actionType": "send_email",
                          "label": "Intro email",
                          "config": {
                            "subject": "Nurses for the summer",
                            "template": "Hi {{first_name}}, …"
                          }
                        }
                      }
                    ],
                    "edges": [
                      {
                        "id": "start-hello",
                        "source": "start",
                        "target": "hello",
                        "source_handle": null,
                        "target_handle": null
                      }
                    ],
                    "settings": {
                      "stopOnReply": true,
                      "name": "Webinar follow-up"
                    }
                  },
                  "compile_error": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_automation",
        "summary": "Rename an automation or replace its flow",
        "description": "`name` renames it (any status). `flow` replaces the graph of a draft or paused automation — pause a running one first (409); a paused one is recompiled when it is turned back on, and contacts mid-flow stay on their own steps.\n\nRequires the `campaigns:write` scope.",
        "tags": [
          "Automations"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "flow": {
                    "type": "object",
                    "properties": {
                      "nodes": {
                        "minItems": 1,
                        "maxItems": 200,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 100
                            },
                            "type": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 60
                            },
                            "position": {
                              "type": "object",
                              "properties": {
                                "x": {
                                  "type": "number"
                                },
                                "y": {
                                  "type": "number"
                                }
                              },
                              "required": [
                                "x",
                                "y"
                              ],
                              "additionalProperties": false
                            },
                            "data": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {},
                              "description": "The node: nodeType (trigger, action or condition), triggerType / actionType / conditionType, label and config — the flow builder's own format."
                            }
                          },
                          "required": [
                            "id",
                            "data"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "edges": {
                        "maxItems": 400,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 200
                            },
                            "source": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 100
                            },
                            "target": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 100
                            },
                            "source_handle": {
                              "description": "yes / no on a condition's outgoing edges.",
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 40
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "target_handle": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 40
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "id",
                            "source",
                            "target"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "settings": {
                        "description": "Flow settings (schedule, days, timezone, stopOnReply …).",
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    },
                    "required": [
                      "nodes",
                      "edges"
                    ],
                    "additionalProperties": false,
                    "description": "An automation's flow graph."
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "name": "Webinar follow-up (EN)"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rename an automation or replace its flow",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "automation"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "draft, active, paused or archived (stopped)."
                    },
                    "trigger": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "What starts the flow (e.g. manual_contacts, landing_form)."
                    },
                    "node_count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "compiled_step_count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Steps in the program the engine runs (set when it is activated)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "flow": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "nodes": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {}
                              }
                            },
                            "edges": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {}
                              }
                            },
                            "settings": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {}
                            }
                          },
                          "required": [
                            "nodes",
                            "edges",
                            "settings"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "compile_error": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Why the flow can't be activated as it is (null = it compiles)."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "status",
                    "trigger",
                    "node_count",
                    "compiled_step_count",
                    "created_at",
                    "flow",
                    "compile_error"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                  "object": "automation",
                  "name": "Webinar follow-up (EN)",
                  "status": "draft",
                  "trigger": "manual_contacts",
                  "node_count": 2,
                  "compiled_step_count": 0,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "flow": {
                    "nodes": [
                      {
                        "id": "start",
                        "type": "trigger",
                        "position": {
                          "x": 0,
                          "y": 0
                        },
                        "data": {
                          "nodeType": "trigger",
                          "triggerType": "manual_contacts",
                          "label": "Picked contacts",
                          "config": {
                            "audience": {
                              "lists": [
                                {
                                  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
                                }
                              ]
                            }
                          }
                        }
                      },
                      {
                        "id": "hello",
                        "type": "action",
                        "position": {
                          "x": 0,
                          "y": 160
                        },
                        "data": {
                          "nodeType": "action",
                          "actionType": "send_email",
                          "label": "Intro email",
                          "config": {
                            "subject": "Nurses for the summer",
                            "template": "Hi {{first_name}}, …"
                          }
                        }
                      }
                    ],
                    "edges": [
                      {
                        "id": "start-hello",
                        "source": "start",
                        "target": "hello",
                        "source_handle": null,
                        "target_handle": null
                      }
                    ],
                    "settings": {
                      "stopOnReply": true,
                      "name": "Webinar follow-up"
                    }
                  },
                  "compile_error": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:write",
        "x-norreach-action": "campaigns.edit",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/automations/{id}/activate": {
      "post": {
        "operationId": "activate_automation",
        "summary": "Activate an automation",
        "description": "Turns a draft or paused automation on, as the builder's Activate does: compiles the flow (422 with the reason if it can't), runs the launch check (409 no_sender when a channel it sends on has no connected sender, or an AI-call step has no AI caller), goes live, lets contacts it held carry on, and enrolls a picked audience. A stopped automation can't be turned back on. `dry_run=true` compiles and checks, and changes nothing.\n\nRequires the `campaigns:launch` scope (reaches people, spends or publishes).",
        "tags": [
          "Automations"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:launch"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Activate an automation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "status_change"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "from": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "The status now (or, in a dry run, the one it would get)."
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "What the launch check found but didn't block on."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "enrolled": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Automations: contacts the activation enrolled (a stop's dry run: contacts it would end). Null otherwise."
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "from",
                    "status",
                    "changed",
                    "dry_run",
                    "warnings",
                    "note",
                    "enrolled"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "status_change",
                  "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                  "from": "draft",
                  "status": "active",
                  "changed": true,
                  "dry_run": false,
                  "warnings": [],
                  "note": null,
                  "enrolled": 42
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `no_sender` — A channel this needs has no connected sender. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:launch",
        "x-norreach-action": "campaigns.launch",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/automations/{id}/analytics": {
      "get": {
        "operationId": "get_automation_analytics",
        "summary": "An automation's numbers",
        "description": "Per compiled step: sent, delivered, opened, clicked, failed, bounced; the replies it got; and the funnel — how many contacts ran and wait at each step, how many are in progress or need attention.\n\nRequires the `campaigns:read` scope.",
        "tags": [
          "Automations"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "An automation's numbers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "automation_analytics"
                    },
                    "automation_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "by_step": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "step_index": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "sent": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "delivered": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "opened": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "clicked": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "failed": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "bounced": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "step_index",
                          "sent",
                          "delivered",
                          "opened",
                          "clicked",
                          "failed",
                          "bounced"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "totals": {
                      "type": "object",
                      "properties": {
                        "sent": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "delivered": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "opened": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "clicked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "failed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "bounced": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "sent",
                        "delivered",
                        "opened",
                        "clicked",
                        "failed",
                        "bounced"
                      ],
                      "additionalProperties": false
                    },
                    "replies": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "funnel": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "in_progress": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "needs_attention": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "passed": {
                          "type": "array",
                          "items": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "description": "Contacts that ran each compiled step."
                        },
                        "waiting": {
                          "type": "array",
                          "items": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "description": "Contacts waiting at each compiled step."
                        }
                      },
                      "required": [
                        "total",
                        "in_progress",
                        "needs_attention",
                        "passed",
                        "waiting"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "object",
                    "automation_id",
                    "by_step",
                    "totals",
                    "replies",
                    "funnel"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "automation_analytics",
                  "automation_id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                  "by_step": [
                    {
                      "step_index": 0,
                      "sent": 40,
                      "delivered": 39,
                      "opened": 18,
                      "clicked": 3,
                      "failed": 0,
                      "bounced": 1
                    }
                  ],
                  "totals": {
                    "sent": 40,
                    "delivered": 39,
                    "opened": 18,
                    "clicked": 3,
                    "failed": 0,
                    "bounced": 1
                  },
                  "replies": 5,
                  "funnel": {
                    "total": 42,
                    "in_progress": 30,
                    "needs_attention": 1,
                    "passed": [
                      40
                    ],
                    "waiting": [
                      2
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/automations/{id}/logs": {
      "get": {
        "operationId": "list_automation_logs",
        "summary": "An automation's execution log",
        "description": "What the engine did for this automation's contacts, newest first (sends, replies, blocked sends, gates timing out, contacts finishing). `has_more` says older entries exist beyond `limit`.\n\nRequires the `campaigns:read` scope.",
        "tags": [
          "Automations"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "An automation's execution log",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "object": {
                            "type": "string",
                            "const": "automation_log"
                          },
                          "at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "type": {
                            "type": "string",
                            "description": "The event (email.sent, send.blocked, enrollment.completed …)."
                          },
                          "label": {
                            "type": "string"
                          },
                          "detail": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "tone": {
                            "type": "string",
                            "enum": [
                              "ok",
                              "warn",
                              "error",
                              "info",
                              "muted"
                            ]
                          },
                          "contact_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "contact_name": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "at",
                          "type",
                          "label",
                          "detail",
                          "tone",
                          "contact_id",
                          "contact_name"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "981",
                      "object": "automation_log",
                      "at": "2026-11-04T09:12:33.120Z",
                      "type": "email.sent",
                      "label": "Email sent",
                      "detail": "Step 1 · email",
                      "tone": "ok",
                      "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                      "contact_name": "Anna Lindqvist"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/automations/{id}/pause": {
      "post": {
        "operationId": "pause_automation",
        "summary": "Pause an automation",
        "description": "Holds a running automation: contacts stay where they are and nothing more is sent until it is activated again.\n\nRequires the `campaigns:launch` scope (reaches people, spends or publishes).",
        "tags": [
          "Automations"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:launch"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pause an automation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "status_change"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "from": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "The status now (or, in a dry run, the one it would get)."
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "What the launch check found but didn't block on."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "enrolled": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Automations: contacts the activation enrolled (a stop's dry run: contacts it would end). Null otherwise."
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "from",
                    "status",
                    "changed",
                    "dry_run",
                    "warnings",
                    "note",
                    "enrolled"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "status_change",
                  "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                  "from": "active",
                  "status": "paused",
                  "changed": true,
                  "dry_run": false,
                  "warnings": [],
                  "note": null,
                  "enrolled": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:launch",
        "x-norreach-action": "campaigns.launch",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/automations/{id}/stop": {
      "post": {
        "operationId": "stop_automation",
        "summary": "Stop an automation for good",
        "description": "Ends the automation permanently (unlike pause it can't be turned back on): every contact still in it stops where they are; messages already sent stay. `dry_run=true` says how many contacts it would stop (`enrolled`).\n\nRequires the `campaigns:launch` scope (reaches people, spends or publishes).",
        "tags": [
          "Automations"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:launch"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stop an automation for good",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "status_change"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "from": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "The status now (or, in a dry run, the one it would get)."
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "What the launch check found but didn't block on."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "enrolled": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Automations: contacts the activation enrolled (a stop's dry run: contacts it would end). Null otherwise."
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "from",
                    "status",
                    "changed",
                    "dry_run",
                    "warnings",
                    "note",
                    "enrolled"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "status_change",
                  "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                  "from": "active",
                  "status": "archived",
                  "changed": true,
                  "dry_run": false,
                  "warnings": [],
                  "note": null,
                  "enrolled": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:launch",
        "x-norreach-action": "campaigns.launch",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/availability": {
      "get": {
        "operationId": "get_availability",
        "summary": "Free times",
        "description": "Free times for a meeting type (default: the booking page's default type) between `from` and `to` (default: the next 7 days; at most 31 days), worked out from the hosts' working hours, calendars, buffers and notice — the same times your booking page offers. Narrow it to one host with `host_id`. Book one with POST /meetings.\n\nRequires the `meetings:read` scope.",
        "tags": [
          "Meetings"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "meetings:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_type_id",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "host_id",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 200,
              "type": "integer",
              "minimum": 1,
              "maximum": 500
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Free times",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "availability"
                    },
                    "meeting_type_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "duration_minutes": {
                      "type": "number"
                    },
                    "timezone": {
                      "type": "string",
                      "description": "The booking page's time zone (slots themselves are UTC)."
                    },
                    "from": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "to": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "slots": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "start": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "end": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "host_ids": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            }
                          }
                        },
                        "required": [
                          "start",
                          "end",
                          "host_ids"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "More free times exist than were returned — narrow the range."
                    }
                  },
                  "required": [
                    "object",
                    "meeting_type_id",
                    "duration_minutes",
                    "timezone",
                    "from",
                    "to",
                    "slots",
                    "truncated"
                  ],
                  "additionalProperties": false,
                  "description": "Free times for a meeting type, from the hosts' working hours and calendars."
                },
                "example": {
                  "object": "availability",
                  "meeting_type_id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                  "duration_minutes": 30,
                  "timezone": "Europe/Stockholm",
                  "from": "2026-11-10T00:00:00.000Z",
                  "to": "2026-11-17T00:00:00.000Z",
                  "slots": [
                    {
                      "start": "2026-11-12T09:00:00.000Z",
                      "end": "2026-11-12T09:30:00.000Z",
                      "host_ids": [
                        "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00"
                      ]
                    }
                  ],
                  "truncated": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "meetings:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/booking-pages": {
      "get": {
        "operationId": "list_booking_pages",
        "summary": "Your booking page",
        "description": "The workspace's booking page (a workspace has one): its address, whether it's live, its time zone and whether bookings made for a contact (by Nora or through the API) wait for a person's yes. Empty when scheduling isn't set up.\n\nRequires the `meetings:read` scope.",
        "tags": [
          "Meetings"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "meetings:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Your booking page",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "The workspace's id (a workspace has one booking page)."
                          },
                          "object": {
                            "type": "string",
                            "const": "booking_page"
                          },
                          "mode": {
                            "type": "string",
                            "enum": [
                              "norreach",
                              "external",
                              "none"
                            ],
                            "description": "norreach: our booking page; external: a link of your own; none: not set up."
                          },
                          "slug": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "url": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The public page (or your own link in external mode)."
                          },
                          "live": {
                            "type": "boolean"
                          },
                          "headline": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "intro": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "timezone": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "default_meeting_type_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "assisted_bookings_need_approval": {
                            "type": "boolean",
                            "description": "Bookings made for a contact (by Nora or through the API) wait for a person's yes."
                          },
                          "updated_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "mode",
                          "slug",
                          "url",
                          "live",
                          "headline",
                          "intro",
                          "timezone",
                          "default_meeting_type_id",
                          "assisted_bookings_need_approval",
                          "updated_at"
                        ],
                        "additionalProperties": false,
                        "description": "The workspace's booking page."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "5c3e2a10-9b8d-4f6e-a1c2-3d4e5f6a7b8c",
                      "object": "booking_page",
                      "mode": "norreach",
                      "slug": "acme",
                      "url": "https://www.norreach.app/book/acme",
                      "live": true,
                      "headline": "Let's talk",
                      "intro": null,
                      "timezone": "Europe/Stockholm",
                      "default_meeting_type_id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                      "assisted_bookings_need_approval": true,
                      "updated_at": "2026-11-01T08:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "meetings:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/briefs": {
      "post": {
        "operationId": "create_brief",
        "summary": "File a brief — Nora writes a plan",
        "description": "Files a brief and asks Nora to write the plan for it: the cards (emails, messages, posts, calls), the landing-page drafts and the ad launches. This is the ONLY way new ads are made through the API — there is no operation that creates, generates or searches ads or creatives. Writing takes minutes, so the answer is 202 with a `plan.generate` job: poll GET /v1/jobs/{id} (its `result.plan_id` names the plan once it is written) or subscribe to the `plan.generated` webhook. The plan lands in review: nothing goes out until it is activated. Lists named in `audience` must be this workspace's. Choosing what Nora may do without asking (`autonomy`, anything but ask_everything) needs the nora:autonomy scope.\n\nRequires the `plans:write` scope.",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "goal": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 600,
                    "description": "What a win looks like, in your words — the one thing Nora can't infer."
                  },
                  "goal_type": {
                    "type": "string",
                    "enum": [
                      "brand_awareness",
                      "lead_gen",
                      "nurture"
                    ]
                  },
                  "duration_days": {
                    "description": "How long the plan runs (default 30).",
                    "type": "integer",
                    "minimum": 7,
                    "maximum": 180
                  },
                  "channels": {
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "channel": {
                          "type": "string",
                          "enum": [
                            "email",
                            "instagram",
                            "facebook",
                            "linkedin",
                            "x",
                            "tiktok",
                            "sms",
                            "whatsapp",
                            "ai_call",
                            "paid_ad"
                          ]
                        },
                        "role": {
                          "type": "string",
                          "enum": [
                            "recommended",
                            "optional"
                          ]
                        },
                        "enabled": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "channel"
                      ],
                      "additionalProperties": false
                    },
                    "description": "The channels the plan may use (at least one switched on)."
                  },
                  "budget": {
                    "type": "object",
                    "properties": {
                      "total_minor": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 1000000000,
                        "description": "The whole budget for paid cards, minor units."
                      },
                      "currency": {
                        "type": "string",
                        "pattern": "^[A-Z]{3}$",
                        "description": "ISO 4217 (SEK, EUR …)."
                      },
                      "per_week_minor": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 1000000000
                      },
                      "ad_networks": {
                        "description": "Where the paid cards run (default Meta).",
                        "minItems": 1,
                        "maxItems": 4,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "enum": [
                            "meta",
                            "tiktok",
                            "reddit",
                            "chatgpt"
                          ]
                        }
                      },
                      "ad_split": {
                        "description": "Percent by network (default equal shares).",
                        "type": "object",
                        "propertyNames": {
                          "type": "string",
                          "enum": [
                            "meta",
                            "tiktok",
                            "reddit",
                            "chatgpt"
                          ]
                        },
                        "additionalProperties": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 100
                        },
                        "required": [
                          "meta",
                          "tiktok",
                          "reddit",
                          "chatgpt"
                        ]
                      }
                    },
                    "required": [
                      "total_minor",
                      "currency"
                    ],
                    "additionalProperties": false
                  },
                  "brand_name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "icp": {
                    "description": "Who the plan is for.",
                    "type": "string",
                    "maxLength": 2000
                  },
                  "priority": {
                    "type": "string",
                    "maxLength": 400
                  },
                  "playbook": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "lead_status": {
                    "type": "string",
                    "enum": [
                      "have",
                      "need"
                    ]
                  },
                  "audience": {
                    "description": "Who the plan runs against once started: every contact, or only these lists. Absent = nobody was asked (the plan starts with no audience).",
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "const": "all"
                          }
                        },
                        "required": [
                          "kind"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "const": "lists"
                          },
                          "list_ids": {
                            "minItems": 1,
                            "maxItems": 20,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            }
                          }
                        },
                        "required": [
                          "kind",
                          "list_ids"
                        ],
                        "additionalProperties": false
                      }
                    ]
                  },
                  "start_date": {
                    "description": "Day one (today to 60 days out, in time_zone).",
                    "type": "string",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                  },
                  "time_zone": {
                    "description": "IANA zone for start_date (e.g. Europe/Stockholm).",
                    "type": "string",
                    "maxLength": 64
                  },
                  "disclose_ai": {
                    "description": "Should an AI caller say it's an AI? (stored with the plan's policies).",
                    "type": "boolean"
                  },
                  "autonomy": {
                    "description": "What Nora may do without asking. Anything but ask_everything needs the nora:autonomy scope.",
                    "type": "object",
                    "properties": {
                      "preset": {
                        "type": "string",
                        "enum": [
                          "ask_everything",
                          "auto_veto",
                          "full_auto"
                        ],
                        "description": "ask_everything = every piece waits for a person; auto_veto = Nora goes ahead unless you stop her; full_auto = Nora runs it."
                      },
                      "policies": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "boolean"
                        },
                        "description": "Per-kind switches. quiet_hours and disclosure are always on."
                      }
                    },
                    "required": [
                      "preset"
                    ],
                    "additionalProperties": false
                  },
                  "answers": {
                    "description": "Extra questions and answers Nora should read.",
                    "maxItems": 40,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "q": {
                          "type": "string",
                          "maxLength": 400
                        },
                        "a": {
                          "type": "string",
                          "maxLength": 2000
                        }
                      },
                      "required": [
                        "q",
                        "a"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "goal",
                  "goal_type",
                  "channels"
                ],
                "additionalProperties": false
              },
              "example": {
                "goal": "20 new nurse placements with Stockholm clinics before Christmas",
                "goal_type": "lead_gen",
                "duration_days": 30,
                "channels": [
                  {
                    "channel": "email"
                  },
                  {
                    "channel": "paid_ad",
                    "role": "optional"
                  }
                ],
                "budget": {
                  "total_minor": 1500000,
                  "currency": "SEK",
                  "ad_networks": [
                    "meta"
                  ]
                },
                "brand_name": "Example Care",
                "icp": "Clinic managers at private care providers in Stockholm",
                "audience": {
                  "kind": "lists",
                  "list_ids": [
                    "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "File a brief — Nora writes a plan",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "job"
                    },
                    "type": {
                      "type": "string",
                      "description": "What the job does (e.g. contacts.import)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "running",
                        "succeeded",
                        "failed"
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "finished_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "result": {
                      "anyOf": [
                        {},
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The job's answer once it succeeded."
                    },
                    "error": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "description": "A URL identifying the problem type."
                            },
                            "title": {
                              "type": "string",
                              "description": "A short, human summary (follows Accept-Language)."
                            },
                            "status": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "The HTTP status."
                            },
                            "code": {
                              "type": "string",
                              "enum": [
                                "bad_request",
                                "unknown_field",
                                "invalid_cursor",
                                "idempotency_key_required",
                                "unauthorized",
                                "key_revoked",
                                "key_expired",
                                "legacy_key",
                                "test_keys_not_available",
                                "key_owner_inactive",
                                "insufficient_scope",
                                "role_forbidden",
                                "ip_not_allowed",
                                "workspace_suspended",
                                "feature_not_enabled",
                                "key_suspended",
                                "member_locked",
                                "not_found",
                                "method_not_allowed",
                                "conflict",
                                "outreach_paused",
                                "already_decided",
                                "idempotency_in_progress",
                                "no_sender",
                                "insufficient_credits",
                                "too_large",
                                "validation_failed",
                                "send_blocked",
                                "publish_blocked",
                                "ad_publish_blocked",
                                "ad_switch_blocked",
                                "ad_network_unsupported",
                                "post_schedule_blocked",
                                "ads_by_plan",
                                "idempotency_mismatch",
                                "rate_limited",
                                "send_cap_reached",
                                "number_cap_reached",
                                "server_error",
                                "unavailable"
                              ],
                              "description": "Stable machine-readable code."
                            },
                            "detail": {
                              "description": "What happened, for a person (follows Accept-Language).",
                              "type": "string"
                            },
                            "instance": {
                              "description": "The request id.",
                              "type": "string"
                            },
                            "errors": {
                              "description": "Field-level problems (validation_failed, unknown_field).",
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "path": {
                                    "type": "string"
                                  },
                                  "code": {
                                    "type": "string"
                                  },
                                  "message": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "path",
                                  "code",
                                  "message"
                                ],
                                "additionalProperties": false
                              }
                            },
                            "docs": {
                              "type": "string",
                              "description": "Where this code is explained."
                            }
                          },
                          "required": [
                            "type",
                            "title",
                            "status",
                            "code",
                            "docs"
                          ],
                          "additionalProperties": {},
                          "description": "RFC 9457 problem details."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Why it failed."
                    },
                    "resource": {
                      "description": "What the job works on — GET it for the full object.",
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "object": {
                              "type": "string",
                              "description": "What kind of thing (e.g. plan)."
                            },
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            }
                          },
                          "required": [
                            "object",
                            "id"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "type",
                    "status",
                    "created_at",
                    "finished_at",
                    "result",
                    "error"
                  ],
                  "additionalProperties": false,
                  "description": "A long-running job."
                },
                "example": {
                  "id": "2f9c1a7e-5b3d-4e8f-9a1b-6c7d8e9f0a1b",
                  "object": "job",
                  "type": "plan.generate",
                  "status": "queued",
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "finished_at": null,
                  "result": null,
                  "error": null,
                  "resource": {
                    "object": "plan",
                    "id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:write",
        "x-norreach-action": "plan.edit",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/calls": {
      "get": {
        "operationId": "list_calls",
        "summary": "List calls",
        "description": "The workspace's calls, newest first, with outcome, duration, sentiment and a short summary. Filter by contact, campaign, status or direction.\n\nRequires the `calls:read` scope.",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "calls:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "campaign_id",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 40
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "outbound",
                "inbound"
              ]
            }
          },
          {
            "name": "created_after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List calls",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "call"
                          },
                          "contact_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "campaign_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "enrollment_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "direction": {
                            "type": "string",
                            "description": "outbound or inbound."
                          },
                          "status": {
                            "type": "string",
                            "description": "initiated, in-progress, completed, no_answer, busy, failed …"
                          },
                          "duration_seconds": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sentiment": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "summary": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "What was said, in a few lines."
                          },
                          "successful": {
                            "anyOf": [
                              {
                                "type": "boolean"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Whether the call reached its goal, when it was judged."
                          },
                          "started_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "ended_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "contact_id",
                          "campaign_id",
                          "enrollment_id",
                          "direction",
                          "status",
                          "duration_seconds",
                          "sentiment",
                          "summary",
                          "successful",
                          "started_at",
                          "ended_at",
                          "created_at"
                        ],
                        "additionalProperties": false,
                        "description": "An AI or human call."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "8b9c0d1e-2f3a-4b4c-9d5e-6f7a8b9c0d1e",
                      "object": "call",
                      "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                      "campaign_id": null,
                      "enrollment_id": null,
                      "direction": "outbound",
                      "status": "completed",
                      "duration_seconds": 184,
                      "sentiment": "positive",
                      "summary": "Maja needs two nurses from June; asked for a call back Thursday.",
                      "successful": true,
                      "started_at": "2026-11-04T09:12:33.120Z",
                      "ended_at": "2026-11-04T09:15:37.120Z",
                      "created_at": "2026-11-04T09:12:30.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "calls:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "request_call",
        "summary": "Request an AI call",
        "description": "Asks the AI caller to call a SAVED contact (`contact_id` — never a free-typed number), optionally under a campaign and with one of your voice agents. It is an API send: it waits in Approvals when the workspace (or the campaign) approves before sending, or when the key lacks `approvals:decide`; `approve: true` (with `approvals:decide`) approves it at once. Up front: suppressed, do-not-contact, no lawful basis or quiet hours → 422 send_blocked with `reason`; a number in a country the workspace doesn't call → 422 send_blocked `country_off`; the API's hourly cap (30 calls per workspace) → 429. The engine checks everything again when it dials. Follow it with GET /calls/{id}.\n\nRequires the `calls:place` scope (reaches people, spends or publishes).",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "calls:place"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contact_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "description": "An id (UUID)."
                  },
                  "campaign_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "description": "An id (UUID)."
                  },
                  "voice_agent_id": {
                    "description": "One of GET /voice-agents (default: the campaign's or the workspace's).",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "approve": {
                    "default": false,
                    "type": "boolean"
                  }
                },
                "required": [
                  "contact_id"
                ],
                "additionalProperties": false
              },
              "example": {
                "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                "voice_agent_id": "9c0d1e2f-3a4b-4c5d-8e6f-7a8b9c0d1e2f"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Request an AI call",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "send_request"
                    },
                    "id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The request's id — poll GET /messages/{id} or GET /calls/{id} with it."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "message",
                        "call"
                      ]
                    },
                    "channel": {
                      "type": "string"
                    },
                    "contact_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "awaiting_approval",
                        "queued",
                        "dry_run"
                      ],
                      "description": "awaiting_approval = it waits in Approvals; queued = approved, it goes out within a minute through the send checks."
                    },
                    "approval_key": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The Approvals key (approve it with POST /approvals/{key}/approve)."
                    },
                    "note": {
                      "type": "string"
                    },
                    "would": {
                      "description": "Dry run: what would happen.",
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "awaiting_approval",
                            "queued"
                          ]
                        }
                      },
                      "required": [
                        "status"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "kind",
                    "channel",
                    "contact_id",
                    "status",
                    "approval_key",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "A send asked for through the API. It never skips the send checks or the approval queue."
                },
                "example": {
                  "object": "send_request",
                  "id": "0d1e2f3a-4b5c-4d6e-9f7a-8b9c0d1e2f3a",
                  "kind": "call",
                  "channel": "call",
                  "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "status": "awaiting_approval",
                  "approval_key": "rule_send:0d1e2f3a-4b5c-4d6e-9f7a-8b9c0d1e2f3a",
                  "note": "It waits in Approvals until someone says yes."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request. · `send_blocked` — This can't be sent to this person.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again. · `send_cap_reached` — The workspace's sending limit for now is reached.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "calls:place",
        "x-norreach-action": "calls.place",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/calls/{id}": {
      "get": {
        "operationId": "get_call",
        "summary": "One call, or where an API call request stands",
        "description": "With a call id: the call. With the `id` POST /calls answered: where the request stands — awaiting_approval, skipped, queued, blocked (with `reason`) or placed (with `call_id`).\n\nRequires the `calls:read` scope.",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "calls:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One call, or where an API call request stands",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        "object": {
                          "type": "string",
                          "const": "call"
                        },
                        "contact_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "campaign_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "enrollment_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "direction": {
                          "type": "string",
                          "description": "outbound or inbound."
                        },
                        "status": {
                          "type": "string",
                          "description": "initiated, in-progress, completed, no_answer, busy, failed …"
                        },
                        "duration_seconds": {
                          "anyOf": [
                            {
                              "type": "number"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "sentiment": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "summary": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "What was said, in a few lines."
                        },
                        "successful": {
                          "anyOf": [
                            {
                              "type": "boolean"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Whether the call reached its goal, when it was judged."
                        },
                        "started_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "ended_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "created_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "object",
                        "contact_id",
                        "campaign_id",
                        "enrollment_id",
                        "direction",
                        "status",
                        "duration_seconds",
                        "sentiment",
                        "summary",
                        "successful",
                        "started_at",
                        "ended_at",
                        "created_at"
                      ],
                      "additionalProperties": false,
                      "description": "An AI or human call."
                    },
                    {
                      "type": "object",
                      "properties": {
                        "object": {
                          "type": "string",
                          "const": "send_request"
                        },
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        "kind": {
                          "type": "string",
                          "const": "call"
                        },
                        "channel": {
                          "type": "string",
                          "const": "call"
                        },
                        "contact_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "state": {
                          "type": "string",
                          "enum": [
                            "awaiting_approval",
                            "skipped",
                            "queued",
                            "blocked",
                            "placed"
                          ]
                        },
                        "reason": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "created_at": {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        "call_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "kind",
                        "channel",
                        "contact_id",
                        "state",
                        "reason",
                        "created_at",
                        "call_id"
                      ],
                      "additionalProperties": false,
                      "description": "A call asked for through the API, by its request id."
                    }
                  ]
                },
                "example": {
                  "id": "8b9c0d1e-2f3a-4b4c-9d5e-6f7a8b9c0d1e",
                  "object": "call",
                  "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "campaign_id": null,
                  "enrollment_id": null,
                  "direction": "outbound",
                  "status": "completed",
                  "duration_seconds": 184,
                  "sentiment": "positive",
                  "summary": "Maja needs two nurses from June; asked for a call back Thursday.",
                  "successful": true,
                  "started_at": "2026-11-04T09:12:33.120Z",
                  "ended_at": "2026-11-04T09:15:37.120Z",
                  "created_at": "2026-11-04T09:12:30.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "calls:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/calls/{id}/transcript": {
      "get": {
        "operationId": "get_call_transcript",
        "summary": "A call's transcript",
        "description": "What was said, turn by turn (`agent` = the AI caller, `contact` = the person). Sensitive: needs `calls:recordings`, and every read is audit-logged.\n\nRequires the `calls:recordings` scope.",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "calls:recordings"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A call's transcript",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "transcript"
                    },
                    "call_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "turns": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "role": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          },
                          "at_seconds": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "role",
                          "message",
                          "at_seconds"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "object",
                    "call_id",
                    "turns"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "transcript",
                  "call_id": "8b9c0d1e-2f3a-4b4c-9d5e-6f7a8b9c0d1e",
                  "turns": [
                    {
                      "role": "agent",
                      "message": "Hi Maja, this is Nora calling for Example Staffing …",
                      "at_seconds": 0
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "calls:recordings",
        "x-norreach-action": "calls.monitor",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/campaigns": {
      "get": {
        "operationId": "list_campaigns",
        "summary": "List campaigns",
        "description": "The workspace's campaigns (broadcasts, sequences and multichannel campaigns — automations are under /automations), newest first, a page at a time. Archived campaigns are left out unless you ask for `status=archived`.\n\nRequires the `campaigns:read` scope.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "active",
                "paused",
                "completed",
                "archived",
                "needs_review"
              ]
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "broadcast",
                "sequence",
                "multichannel"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List campaigns",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "campaign"
                          },
                          "name": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "description": "draft, active, paused, completed, archived or needs_review."
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "broadcast",
                              "sequence",
                              "multichannel"
                            ]
                          },
                          "channels": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "The channel mix of the sequence, in order."
                          },
                          "step_count": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "brand_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "schedule_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "name",
                          "status",
                          "kind",
                          "channels",
                          "step_count",
                          "brand_id",
                          "schedule_at",
                          "created_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                      "object": "campaign",
                      "name": "Summer nurses — Stockholm",
                      "status": "draft",
                      "kind": "sequence",
                      "channels": [
                        "email",
                        "sms"
                      ],
                      "step_count": 2,
                      "brand_id": null,
                      "schedule_at": null,
                      "created_at": "2026-11-04T09:12:33.120Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "create_campaign",
        "summary": "Create a draft campaign",
        "description": "Saves a new campaign as a draft — nothing is sent until it is launched (POST /campaigns/{id}/launch). The sequence may start empty; a broadcast is exactly one step and never LinkedIn. Every AI caller and brand named must be this workspace's.\n\nRequires the `campaigns:write` scope.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "broadcast",
                      "sequence",
                      "multichannel"
                    ]
                  },
                  "steps": {
                    "default": [],
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "channel": {
                          "type": "string",
                          "enum": [
                            "email",
                            "sms",
                            "whatsapp",
                            "call",
                            "linkedin"
                          ]
                        },
                        "wait_hours": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 8760,
                          "description": "Hours to wait before this step (after the previous one)."
                        },
                        "template": {
                          "description": "The words. Email: \"Subject: <line>\\n\\n<body>\". WhatsApp: the approved template's name. Merge tags like {{first_name}} are filled per contact.",
                          "type": "string",
                          "maxLength": 20000
                        },
                        "li_kind": {
                          "description": "LinkedIn steps: what the step does.",
                          "type": "string",
                          "enum": [
                            "connect",
                            "message",
                            "like_post"
                          ]
                        },
                        "agent_id": {
                          "description": "AI-call steps: which of the workspace's AI callers places the call.",
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "retry_if_no_answer": {
                          "description": "AI-call steps: retry an unanswered call.",
                          "type": "object",
                          "properties": {
                            "enabled": {
                              "type": "boolean",
                              "description": "Dial again when nobody answered or the line was busy."
                            },
                            "attempts": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 3
                            },
                            "gap_minutes": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 10080
                            },
                            "on_voicemail": {
                              "description": "Also dial again when a voicemail answered.",
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "enabled",
                            "attempts",
                            "gap_minutes"
                          ],
                          "additionalProperties": false
                        },
                        "ai_drafted": {
                          "type": "boolean"
                        },
                        "coaching": {
                          "description": "Notes for Nora about this step.",
                          "type": "string",
                          "maxLength": 2000
                        },
                        "wa_language": {
                          "description": "WhatsApp steps: the approved template's language code (e.g. en_US).",
                          "type": "string",
                          "maxLength": 20
                        },
                        "wa_params": {
                          "description": "WhatsApp steps: the values for {{1}}…{{n}}, in order (text or merge tags).",
                          "maxItems": 20,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "maxLength": 500
                          }
                        },
                        "branch": {
                          "description": "Wait for a signal after this step; without it the contact jumps ahead.",
                          "type": "object",
                          "properties": {
                            "on": {
                              "description": "The signal that takes the branch path.",
                              "type": "string",
                              "enum": [
                                "accepted",
                                "replied",
                                "opened",
                                "clicked"
                              ]
                            },
                            "timeout_hours": {
                              "type": "number",
                              "exclusiveMinimum": 0,
                              "maximum": 8760
                            },
                            "timeout_to": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 50,
                              "description": "The step (0-based index) a contact jumps to when the signal doesn't arrive in time."
                            }
                          },
                          "required": [
                            "timeout_hours",
                            "timeout_to"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "channel",
                        "wait_hours"
                      ],
                      "additionalProperties": false,
                      "description": "One step of a sequence."
                    }
                  },
                  "rules": {
                    "default": [],
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 80
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "active",
                            "paused"
                          ]
                        },
                        "when": {
                          "type": "object",
                          "properties": {
                            "event": {
                              "type": "string",
                              "enum": [
                                "replied",
                                "opened",
                                "clicked",
                                "connection_accepted",
                                "meeting_booked",
                                "bounced"
                              ]
                            },
                            "count_gte": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 100
                            }
                          },
                          "required": [
                            "event"
                          ],
                          "additionalProperties": false
                        },
                        "then": {
                          "type": "object",
                          "properties": {
                            "action": {
                              "type": "string",
                              "enum": [
                                "ai_call",
                                "pause",
                                "complete",
                                "book_meeting"
                              ]
                            }
                          },
                          "required": [
                            "action"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "when",
                        "then"
                      ],
                      "additionalProperties": false,
                      "description": "When something happens to a contact in the campaign, do something."
                    }
                  },
                  "settings": {
                    "type": "object",
                    "properties": {
                      "approve_before_send": {
                        "description": "manual = every send waits for a person's yes. Setting auto needs the nora:autonomy scope.",
                        "type": "string",
                        "enum": [
                          "auto",
                          "manual"
                        ]
                      },
                      "reply_autonomously": {
                        "description": "Nora answers replies on her own. Setting true needs the nora:autonomy scope.",
                        "type": "boolean"
                      },
                      "unsubscribe": {
                        "description": "Unsubscribe link settings."
                      },
                      "unsubscribe_mode": {
                        "description": "How opting out works."
                      },
                      "unsubscribe_phrase": {
                        "description": "The opt-out wording."
                      },
                      "reengage": {
                        "description": "Re-engagement settings."
                      },
                      "follow_up_thread": {
                        "description": "Send follow-ups in the same email thread."
                      },
                      "prioritize": {
                        "description": "new, followups or both."
                      },
                      "ooo_pause": {
                        "description": "Pause a contact who is out of office."
                      },
                      "sending": {
                        "description": "Sending window and pacing."
                      },
                      "reply_handling": {
                        "description": "What happens when a contact replies."
                      },
                      "leads_per_day": {
                        "description": "New contacts started per day."
                      },
                      "prospects_per_month": {
                        "description": "Prospects per month."
                      },
                      "pause_on_reply": {
                        "description": "Stop the sequence for a contact who replies."
                      },
                      "exit_on_call_connected": {
                        "description": "Stop the sequence for a contact once an AI call connects."
                      },
                      "call_on_intent": {
                        "description": "Place an AI call when a contact shows intent."
                      },
                      "deliverability": {
                        "description": "Deliverability settings."
                      },
                      "exclusions": {
                        "description": "Who is skipped at enrollment (recency_days, per_company_cap)."
                      },
                      "enforce_sending_window": {
                        "description": "Only send inside the sending window."
                      },
                      "messaging": {
                        "description": "Message writing preferences."
                      },
                      "schedule_at": {
                        "description": "A scheduled start (launching then waits until this time).",
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      }
                    },
                    "additionalProperties": false,
                    "description": "Campaign settings (a sparse override of the workspace's defaults)."
                  },
                  "brand_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "description": "An id (UUID)."
                  },
                  "schedule_at": {
                    "description": "A scheduled start (must be in the future).",
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "Summer nurses — Stockholm",
                "kind": "sequence",
                "steps": [
                  {
                    "channel": "email",
                    "wait_hours": 0,
                    "template": "Subject: Nurses for the summer\n\nHi {{first_name}}, …"
                  },
                  {
                    "channel": "sms",
                    "wait_hours": 48,
                    "template": "Hi {{first_name}}, did you see my email?"
                  }
                ],
                "rules": [
                  {
                    "name": "Stop on reply",
                    "when": {
                      "event": "replied"
                    },
                    "then": {
                      "action": "pause"
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Create a draft campaign",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "campaign"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "draft, active, paused, completed, archived or needs_review."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "broadcast",
                        "sequence",
                        "multichannel"
                      ]
                    },
                    "channels": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The channel mix of the sequence, in order."
                    },
                    "step_count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "brand_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "schedule_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "steps": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      },
                      "description": "The sequence (the step shape above)."
                    },
                    "rules": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    },
                    "settings": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "The campaign's own settings override."
                    },
                    "stats": {
                      "type": "object",
                      "properties": {
                        "enrolled": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "in_progress": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "paused": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "completed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "replied": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "meetings_booked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "sent": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "delivered": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "opened": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "clicked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "enrolled",
                        "in_progress",
                        "paused",
                        "completed",
                        "replied",
                        "meetings_booked",
                        "sent",
                        "delivered",
                        "opened",
                        "clicked"
                      ],
                      "additionalProperties": false,
                      "description": "The campaign's numbers right now."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "status",
                    "kind",
                    "channels",
                    "step_count",
                    "brand_id",
                    "schedule_at",
                    "created_at",
                    "steps",
                    "rules",
                    "settings",
                    "stats"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "object": "campaign",
                  "name": "Summer nurses — Stockholm",
                  "status": "draft",
                  "kind": "sequence",
                  "channels": [
                    "email",
                    "sms"
                  ],
                  "step_count": 2,
                  "brand_id": null,
                  "schedule_at": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "steps": [
                    {
                      "channel": "email",
                      "wait_hours": 0,
                      "template": "Subject: Nurses for the summer\n\nHi {{first_name}}, …"
                    },
                    {
                      "channel": "sms",
                      "wait_hours": 48,
                      "template": "Hi {{first_name}}, did you see my email?"
                    }
                  ],
                  "rules": [
                    {
                      "name": "Stop on reply",
                      "when": {
                        "event": "replied"
                      },
                      "then": {
                        "action": "pause"
                      }
                    }
                  ],
                  "settings": {
                    "approve_before_send": "manual"
                  },
                  "stats": {
                    "enrolled": 120,
                    "in_progress": 80,
                    "paused": 4,
                    "completed": 20,
                    "replied": 14,
                    "meetings_booked": 2,
                    "sent": 210,
                    "delivered": 204,
                    "opened": 96,
                    "clicked": 12
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:write",
        "x-norreach-action": "campaigns.edit",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/campaigns/{id}": {
      "get": {
        "operationId": "get_campaign",
        "summary": "One campaign",
        "description": "A campaign with its sequence, rules, its own settings override and its numbers right now (enrolled, in progress, replied, meetings, sent, delivered, opened, clicked).\n\nRequires the `campaigns:read` scope.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One campaign",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "campaign"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "draft, active, paused, completed, archived or needs_review."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "broadcast",
                        "sequence",
                        "multichannel"
                      ]
                    },
                    "channels": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The channel mix of the sequence, in order."
                    },
                    "step_count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "brand_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "schedule_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "steps": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      },
                      "description": "The sequence (the step shape above)."
                    },
                    "rules": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    },
                    "settings": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "The campaign's own settings override."
                    },
                    "stats": {
                      "type": "object",
                      "properties": {
                        "enrolled": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "in_progress": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "paused": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "completed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "replied": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "meetings_booked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "sent": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "delivered": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "opened": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "clicked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "enrolled",
                        "in_progress",
                        "paused",
                        "completed",
                        "replied",
                        "meetings_booked",
                        "sent",
                        "delivered",
                        "opened",
                        "clicked"
                      ],
                      "additionalProperties": false,
                      "description": "The campaign's numbers right now."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "status",
                    "kind",
                    "channels",
                    "step_count",
                    "brand_id",
                    "schedule_at",
                    "created_at",
                    "steps",
                    "rules",
                    "settings",
                    "stats"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "object": "campaign",
                  "name": "Summer nurses — Stockholm",
                  "status": "draft",
                  "kind": "sequence",
                  "channels": [
                    "email",
                    "sms"
                  ],
                  "step_count": 2,
                  "brand_id": null,
                  "schedule_at": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "steps": [
                    {
                      "channel": "email",
                      "wait_hours": 0,
                      "template": "Subject: Nurses for the summer\n\nHi {{first_name}}, …"
                    },
                    {
                      "channel": "sms",
                      "wait_hours": 48,
                      "template": "Hi {{first_name}}, did you see my email?"
                    }
                  ],
                  "rules": [
                    {
                      "name": "Stop on reply",
                      "when": {
                        "event": "replied"
                      },
                      "then": {
                        "action": "pause"
                      }
                    }
                  ],
                  "settings": {
                    "approve_before_send": "manual"
                  },
                  "stats": {
                    "enrolled": 120,
                    "in_progress": 80,
                    "paused": 4,
                    "completed": 20,
                    "replied": 14,
                    "meetings_booked": 2,
                    "sent": 210,
                    "delivered": 204,
                    "opened": 96,
                    "clicked": 12
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_campaign",
        "summary": "Change a campaign's basics or settings",
        "description": "`name` and `brand_id` change on drafts only (a live campaign is cloned to change). `settings` (a sparse override — only the keys you send change) can change on drafts, live and paused campaigns. Letting sends go out without approval (`approve_before_send` auto) or Nora answer replies on her own (`reply_autonomously` true) needs the nora:autonomy scope; asking for more approval never does.\n\nRequires the `campaigns:write` scope.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "brand_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "settings": {
                    "type": "object",
                    "properties": {
                      "approve_before_send": {
                        "description": "manual = every send waits for a person's yes. Setting auto needs the nora:autonomy scope.",
                        "type": "string",
                        "enum": [
                          "auto",
                          "manual"
                        ]
                      },
                      "reply_autonomously": {
                        "description": "Nora answers replies on her own. Setting true needs the nora:autonomy scope.",
                        "type": "boolean"
                      },
                      "unsubscribe": {
                        "description": "Unsubscribe link settings."
                      },
                      "unsubscribe_mode": {
                        "description": "How opting out works."
                      },
                      "unsubscribe_phrase": {
                        "description": "The opt-out wording."
                      },
                      "reengage": {
                        "description": "Re-engagement settings."
                      },
                      "follow_up_thread": {
                        "description": "Send follow-ups in the same email thread."
                      },
                      "prioritize": {
                        "description": "new, followups or both."
                      },
                      "ooo_pause": {
                        "description": "Pause a contact who is out of office."
                      },
                      "sending": {
                        "description": "Sending window and pacing."
                      },
                      "reply_handling": {
                        "description": "What happens when a contact replies."
                      },
                      "leads_per_day": {
                        "description": "New contacts started per day."
                      },
                      "prospects_per_month": {
                        "description": "Prospects per month."
                      },
                      "pause_on_reply": {
                        "description": "Stop the sequence for a contact who replies."
                      },
                      "exit_on_call_connected": {
                        "description": "Stop the sequence for a contact once an AI call connects."
                      },
                      "call_on_intent": {
                        "description": "Place an AI call when a contact shows intent."
                      },
                      "deliverability": {
                        "description": "Deliverability settings."
                      },
                      "exclusions": {
                        "description": "Who is skipped at enrollment (recency_days, per_company_cap)."
                      },
                      "enforce_sending_window": {
                        "description": "Only send inside the sending window."
                      },
                      "messaging": {
                        "description": "Message writing preferences."
                      },
                      "schedule_at": {
                        "description": "A scheduled start (launching then waits until this time).",
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      }
                    },
                    "additionalProperties": false,
                    "description": "Campaign settings (a sparse override of the workspace's defaults)."
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "settings": {
                  "approve_before_send": "manual"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Change a campaign's basics or settings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "campaign"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "draft, active, paused, completed, archived or needs_review."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "broadcast",
                        "sequence",
                        "multichannel"
                      ]
                    },
                    "channels": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The channel mix of the sequence, in order."
                    },
                    "step_count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "brand_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "schedule_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "steps": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      },
                      "description": "The sequence (the step shape above)."
                    },
                    "rules": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    },
                    "settings": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "The campaign's own settings override."
                    },
                    "stats": {
                      "type": "object",
                      "properties": {
                        "enrolled": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "in_progress": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "paused": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "completed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "replied": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "meetings_booked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "sent": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "delivered": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "opened": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "clicked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "enrolled",
                        "in_progress",
                        "paused",
                        "completed",
                        "replied",
                        "meetings_booked",
                        "sent",
                        "delivered",
                        "opened",
                        "clicked"
                      ],
                      "additionalProperties": false,
                      "description": "The campaign's numbers right now."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "status",
                    "kind",
                    "channels",
                    "step_count",
                    "brand_id",
                    "schedule_at",
                    "created_at",
                    "steps",
                    "rules",
                    "settings",
                    "stats"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "object": "campaign",
                  "name": "Summer nurses — Stockholm",
                  "status": "draft",
                  "kind": "sequence",
                  "channels": [
                    "email",
                    "sms"
                  ],
                  "step_count": 2,
                  "brand_id": null,
                  "schedule_at": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "steps": [
                    {
                      "channel": "email",
                      "wait_hours": 0,
                      "template": "Subject: Nurses for the summer\n\nHi {{first_name}}, …"
                    },
                    {
                      "channel": "sms",
                      "wait_hours": 48,
                      "template": "Hi {{first_name}}, did you see my email?"
                    }
                  ],
                  "rules": [
                    {
                      "name": "Stop on reply",
                      "when": {
                        "event": "replied"
                      },
                      "then": {
                        "action": "pause"
                      }
                    }
                  ],
                  "settings": {
                    "approve_before_send": "manual"
                  },
                  "stats": {
                    "enrolled": 120,
                    "in_progress": 80,
                    "paused": 4,
                    "completed": 20,
                    "replied": 14,
                    "meetings_booked": 2,
                    "sent": 210,
                    "delivered": 204,
                    "opened": 96,
                    "clicked": 12
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:write",
        "x-norreach-action": "campaigns.edit",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/campaigns/{id}/clone": {
      "post": {
        "operationId": "clone_campaign",
        "summary": "Clone a campaign",
        "description": "Copies a campaign (sequence, rules and settings) as a new draft named “… (copy)” — the way to change a live campaign. Contacts aren't copied.\n\nRequires the `campaigns:write` scope.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Clone a campaign",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "campaign"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "draft, active, paused, completed, archived or needs_review."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "broadcast",
                        "sequence",
                        "multichannel"
                      ]
                    },
                    "channels": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The channel mix of the sequence, in order."
                    },
                    "step_count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "brand_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "schedule_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "steps": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      },
                      "description": "The sequence (the step shape above)."
                    },
                    "rules": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    },
                    "settings": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "The campaign's own settings override."
                    },
                    "stats": {
                      "type": "object",
                      "properties": {
                        "enrolled": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "in_progress": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "paused": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "completed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "replied": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "meetings_booked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "sent": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "delivered": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "opened": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "clicked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "enrolled",
                        "in_progress",
                        "paused",
                        "completed",
                        "replied",
                        "meetings_booked",
                        "sent",
                        "delivered",
                        "opened",
                        "clicked"
                      ],
                      "additionalProperties": false,
                      "description": "The campaign's numbers right now."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "status",
                    "kind",
                    "channels",
                    "step_count",
                    "brand_id",
                    "schedule_at",
                    "created_at",
                    "steps",
                    "rules",
                    "settings",
                    "stats"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "object": "campaign",
                  "name": "Summer nurses — Stockholm (copy)",
                  "status": "draft",
                  "kind": "sequence",
                  "channels": [
                    "email",
                    "sms"
                  ],
                  "step_count": 2,
                  "brand_id": null,
                  "schedule_at": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "steps": [
                    {
                      "channel": "email",
                      "wait_hours": 0,
                      "template": "Subject: Nurses for the summer\n\nHi {{first_name}}, …"
                    },
                    {
                      "channel": "sms",
                      "wait_hours": 48,
                      "template": "Hi {{first_name}}, did you see my email?"
                    }
                  ],
                  "rules": [
                    {
                      "name": "Stop on reply",
                      "when": {
                        "event": "replied"
                      },
                      "then": {
                        "action": "pause"
                      }
                    }
                  ],
                  "settings": {
                    "approve_before_send": "manual"
                  },
                  "stats": {
                    "enrolled": 120,
                    "in_progress": 80,
                    "paused": 4,
                    "completed": 20,
                    "replied": 14,
                    "meetings_booked": 2,
                    "sent": 210,
                    "delivered": 204,
                    "opened": 96,
                    "clicked": 12
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:write",
        "x-norreach-action": "campaigns.edit",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/campaigns/{id}/enrollments": {
      "get": {
        "operationId": "list_campaign_enrollments",
        "summary": "List a campaign's enrollments",
        "description": "Who is in the campaign and where each contact is (state, step, why it is paused), newest first, a page at a time. Filter by `state`.\n\nRequires the `campaigns:read` scope.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "active",
                "paused",
                "completed",
                "replied",
                "suppressed",
                "meeting_booked",
                "awaiting_engagement",
                "waiting",
                "calling",
                "scheduled"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List a campaign's enrollments",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "enrollment"
                          },
                          "campaign_id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "contact_id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "contact": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "name": {
                                    "type": "string"
                                  },
                                  "email": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  }
                                },
                                "required": [
                                  "name",
                                  "email"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "state": {
                            "type": "string",
                            "description": "pending, active, paused, completed, replied, suppressed, meeting_booked …"
                          },
                          "current_step": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "The step (0-based) the contact is on."
                          },
                          "pause_reason": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Why it is paused (e.g. awaiting_approval, campaign_not_active, no_consent)."
                          },
                          "next_run_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "updated_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "campaign_id",
                          "contact_id",
                          "contact",
                          "state",
                          "current_step",
                          "pause_reason",
                          "next_run_at",
                          "created_at",
                          "updated_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "8e9f0a1b-2c3d-4e4f-9a5b-6c7d8e9f0a1b",
                      "object": "enrollment",
                      "campaign_id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                      "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                      "contact": {
                        "name": "Anna Lindqvist",
                        "email": "anna@example.com"
                      },
                      "state": "paused",
                      "current_step": 1,
                      "pause_reason": "awaiting_approval",
                      "next_run_at": null,
                      "created_at": "2026-11-04T09:12:33.120Z",
                      "updated_at": "2026-11-04T10:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "enroll_contacts",
        "summary": "Enroll contacts",
        "description": "Puts contacts into a campaign: `contact_ids` (up to 10,000) or every contact on a `list_id` (a list of at most as many). Only this workspace's contacts are enrolled (others come back in `not_found_ids`); contacts already in the campaign are skipped and reported, never enrolled twice; the campaign's own enrollment rules may exclude some (`excluded`). A live campaign starts them now — or holds each first send in Approvals when it asks before sending; a draft or paused one holds them until it runs. At most 50 000 new enrollments a day per workspace (429 send_cap_reached). The suppression list, consent and quiet hours are checked again at every send. Also needs campaigns:write (it changes the campaign's audience).\n\nRequires the `campaigns:launch` scope (reaches people, spends or publishes).",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:launch"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contact_ids": {
                    "minItems": 1,
                    "maxItems": 10000,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    }
                  },
                  "list_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "description": "An id (UUID)."
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "contact_ids": [
                  "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enroll contacts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "enrollment_result"
                    },
                    "campaign_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "requested": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Distinct contacts asked for."
                    },
                    "enrolled": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "New enrollments made (or, in a dry run, at most this many)."
                    },
                    "already_enrolled": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "already_enrolled_ids": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      }
                    },
                    "not_found": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Ids that aren't contacts of this workspace — never enrolled."
                    },
                    "not_found_ids": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "excluded": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Skipped by the campaign's own enrollment rules (recently messaged, per-company cap)."
                    },
                    "held_for_approval": {
                      "type": "boolean",
                      "description": "The campaign asks before it sends: each first send waits in Approvals."
                    },
                    "remaining_contact_ids": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      "description": "Not processed this time (the request ran out of time) — send them again; already enrolled contacts are skipped."
                    }
                  },
                  "required": [
                    "object",
                    "campaign_id",
                    "dry_run",
                    "requested",
                    "enrolled",
                    "already_enrolled",
                    "already_enrolled_ids",
                    "not_found",
                    "not_found_ids",
                    "excluded",
                    "held_for_approval",
                    "remaining_contact_ids"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "enrollment_result",
                  "campaign_id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "dry_run": false,
                  "requested": 2,
                  "enrolled": 1,
                  "already_enrolled": 1,
                  "already_enrolled_ids": [
                    "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
                  ],
                  "not_found": 0,
                  "not_found_ids": [],
                  "excluded": 0,
                  "held_for_approval": false,
                  "remaining_contact_ids": []
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again. · `send_cap_reached` — The workspace's sending limit for now is reached.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:launch",
        "x-norreach-action": "campaigns.launch",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/campaigns/{id}/launch": {
      "post": {
        "operationId": "launch_campaign",
        "summary": "Launch a campaign",
        "description": "Takes a draft live. Runs the same launch check as the app: every channel the sequence sends on needs a connected sender (409 no_sender with what to connect), an AI-call step needs an AI caller. Contacts already enrolled start (honouring a scheduled start). `dry_run=true` runs the checks and changes nothing. A paused campaign is resumed with /resume.\n\nRequires the `campaigns:launch` scope (reaches people, spends or publishes).",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:launch"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Launch a campaign",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "status_change"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "from": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "The status now (or, in a dry run, the one it would get)."
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "What the launch check found but didn't block on."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "enrolled": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Automations: contacts the activation enrolled (a stop's dry run: contacts it would end). Null otherwise."
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "from",
                    "status",
                    "changed",
                    "dry_run",
                    "warnings",
                    "note",
                    "enrolled"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "status_change",
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "from": "draft",
                  "status": "active",
                  "changed": true,
                  "dry_run": false,
                  "warnings": [],
                  "note": null,
                  "enrolled": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `no_sender` — A channel this needs has no connected sender. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:launch",
        "x-norreach-action": "campaigns.launch",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/campaigns/{id}/pause": {
      "post": {
        "operationId": "pause_campaign",
        "summary": "Pause a campaign",
        "description": "Holds every contact where they are: nothing more is sent until it is resumed. Pausing a paused campaign changes nothing.\n\nRequires the `campaigns:launch` scope (reaches people, spends or publishes).",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:launch"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pause a campaign",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "status_change"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "from": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "The status now (or, in a dry run, the one it would get)."
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "What the launch check found but didn't block on."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "enrolled": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Automations: contacts the activation enrolled (a stop's dry run: contacts it would end). Null otherwise."
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "from",
                    "status",
                    "changed",
                    "dry_run",
                    "warnings",
                    "note",
                    "enrolled"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "status_change",
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "from": "active",
                  "status": "paused",
                  "changed": true,
                  "dry_run": false,
                  "warnings": [],
                  "note": null,
                  "enrolled": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:launch",
        "x-norreach-action": "campaigns.launch",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/campaigns/{id}/resume": {
      "post": {
        "operationId": "resume_campaign",
        "summary": "Resume a paused campaign",
        "description": "Puts a paused campaign back live; contacts carry on from where they were. Runs the same launch check as the app: every channel the sequence sends on needs a connected sender (409 no_sender with what to connect), an AI-call step needs an AI caller. Contacts already enrolled start (honouring a scheduled start). `dry_run=true` runs the checks and changes nothing.\n\nRequires the `campaigns:launch` scope (reaches people, spends or publishes).",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:launch"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resume a paused campaign",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "status_change"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "from": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "The status now (or, in a dry run, the one it would get)."
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "What the launch check found but didn't block on."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "enrolled": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Automations: contacts the activation enrolled (a stop's dry run: contacts it would end). Null otherwise."
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "from",
                    "status",
                    "changed",
                    "dry_run",
                    "warnings",
                    "note",
                    "enrolled"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "status_change",
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "from": "paused",
                  "status": "active",
                  "changed": true,
                  "dry_run": false,
                  "warnings": [],
                  "note": null,
                  "enrolled": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `no_sender` — A channel this needs has no connected sender. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:launch",
        "x-norreach-action": "campaigns.launch",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/campaigns/{id}/rules": {
      "put": {
        "operationId": "replace_campaign_rules",
        "summary": "Replace a draft's rules",
        "description": "Replaces the rules of a draft campaign (when a contact replies, opens, clicks, accepts, books or bounces → place an AI call, pause, complete or book a meeting). A live campaign is cloned to change — 409.\n\nRequires the `campaigns:write` scope.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rules": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 80
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "active",
                            "paused"
                          ]
                        },
                        "when": {
                          "type": "object",
                          "properties": {
                            "event": {
                              "type": "string",
                              "enum": [
                                "replied",
                                "opened",
                                "clicked",
                                "connection_accepted",
                                "meeting_booked",
                                "bounced"
                              ]
                            },
                            "count_gte": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 100
                            }
                          },
                          "required": [
                            "event"
                          ],
                          "additionalProperties": false
                        },
                        "then": {
                          "type": "object",
                          "properties": {
                            "action": {
                              "type": "string",
                              "enum": [
                                "ai_call",
                                "pause",
                                "complete",
                                "book_meeting"
                              ]
                            }
                          },
                          "required": [
                            "action"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "when",
                        "then"
                      ],
                      "additionalProperties": false,
                      "description": "When something happens to a contact in the campaign, do something."
                    }
                  }
                },
                "required": [
                  "rules"
                ],
                "additionalProperties": false
              },
              "example": {
                "rules": [
                  {
                    "name": "Stop on reply",
                    "when": {
                      "event": "replied"
                    },
                    "then": {
                      "action": "pause"
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replace a draft's rules",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "campaign"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "draft, active, paused, completed, archived or needs_review."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "broadcast",
                        "sequence",
                        "multichannel"
                      ]
                    },
                    "channels": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The channel mix of the sequence, in order."
                    },
                    "step_count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "brand_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "schedule_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "steps": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      },
                      "description": "The sequence (the step shape above)."
                    },
                    "rules": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    },
                    "settings": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "The campaign's own settings override."
                    },
                    "stats": {
                      "type": "object",
                      "properties": {
                        "enrolled": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "in_progress": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "paused": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "completed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "replied": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "meetings_booked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "sent": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "delivered": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "opened": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "clicked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "enrolled",
                        "in_progress",
                        "paused",
                        "completed",
                        "replied",
                        "meetings_booked",
                        "sent",
                        "delivered",
                        "opened",
                        "clicked"
                      ],
                      "additionalProperties": false,
                      "description": "The campaign's numbers right now."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "status",
                    "kind",
                    "channels",
                    "step_count",
                    "brand_id",
                    "schedule_at",
                    "created_at",
                    "steps",
                    "rules",
                    "settings",
                    "stats"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "object": "campaign",
                  "name": "Summer nurses — Stockholm",
                  "status": "draft",
                  "kind": "sequence",
                  "channels": [
                    "email",
                    "sms"
                  ],
                  "step_count": 2,
                  "brand_id": null,
                  "schedule_at": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "steps": [
                    {
                      "channel": "email",
                      "wait_hours": 0,
                      "template": "Subject: Nurses for the summer\n\nHi {{first_name}}, …"
                    },
                    {
                      "channel": "sms",
                      "wait_hours": 48,
                      "template": "Hi {{first_name}}, did you see my email?"
                    }
                  ],
                  "rules": [
                    {
                      "name": "Stop on reply",
                      "when": {
                        "event": "replied"
                      },
                      "then": {
                        "action": "pause"
                      }
                    }
                  ],
                  "settings": {
                    "approve_before_send": "manual"
                  },
                  "stats": {
                    "enrolled": 120,
                    "in_progress": 80,
                    "paused": 4,
                    "completed": 20,
                    "replied": 14,
                    "meetings_booked": 2,
                    "sent": 210,
                    "delivered": 204,
                    "opened": 96,
                    "clicked": 12
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:write",
        "x-norreach-action": "campaigns.edit",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/campaigns/{id}/sequence": {
      "put": {
        "operationId": "replace_campaign_sequence",
        "summary": "Replace a draft's sequence",
        "description": "Replaces the steps of a draft campaign (a live one is cloned to change — 409). Every AI caller a step names must be this workspace's.\n\nRequires the `campaigns:write` scope.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "steps": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "channel": {
                          "type": "string",
                          "enum": [
                            "email",
                            "sms",
                            "whatsapp",
                            "call",
                            "linkedin"
                          ]
                        },
                        "wait_hours": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 8760,
                          "description": "Hours to wait before this step (after the previous one)."
                        },
                        "template": {
                          "description": "The words. Email: \"Subject: <line>\\n\\n<body>\". WhatsApp: the approved template's name. Merge tags like {{first_name}} are filled per contact.",
                          "type": "string",
                          "maxLength": 20000
                        },
                        "li_kind": {
                          "description": "LinkedIn steps: what the step does.",
                          "type": "string",
                          "enum": [
                            "connect",
                            "message",
                            "like_post"
                          ]
                        },
                        "agent_id": {
                          "description": "AI-call steps: which of the workspace's AI callers places the call.",
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "retry_if_no_answer": {
                          "description": "AI-call steps: retry an unanswered call.",
                          "type": "object",
                          "properties": {
                            "enabled": {
                              "type": "boolean",
                              "description": "Dial again when nobody answered or the line was busy."
                            },
                            "attempts": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 3
                            },
                            "gap_minutes": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 10080
                            },
                            "on_voicemail": {
                              "description": "Also dial again when a voicemail answered.",
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "enabled",
                            "attempts",
                            "gap_minutes"
                          ],
                          "additionalProperties": false
                        },
                        "ai_drafted": {
                          "type": "boolean"
                        },
                        "coaching": {
                          "description": "Notes for Nora about this step.",
                          "type": "string",
                          "maxLength": 2000
                        },
                        "wa_language": {
                          "description": "WhatsApp steps: the approved template's language code (e.g. en_US).",
                          "type": "string",
                          "maxLength": 20
                        },
                        "wa_params": {
                          "description": "WhatsApp steps: the values for {{1}}…{{n}}, in order (text or merge tags).",
                          "maxItems": 20,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "maxLength": 500
                          }
                        },
                        "branch": {
                          "description": "Wait for a signal after this step; without it the contact jumps ahead.",
                          "type": "object",
                          "properties": {
                            "on": {
                              "description": "The signal that takes the branch path.",
                              "type": "string",
                              "enum": [
                                "accepted",
                                "replied",
                                "opened",
                                "clicked"
                              ]
                            },
                            "timeout_hours": {
                              "type": "number",
                              "exclusiveMinimum": 0,
                              "maximum": 8760
                            },
                            "timeout_to": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 50,
                              "description": "The step (0-based index) a contact jumps to when the signal doesn't arrive in time."
                            }
                          },
                          "required": [
                            "timeout_hours",
                            "timeout_to"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "channel",
                        "wait_hours"
                      ],
                      "additionalProperties": false,
                      "description": "One step of a sequence."
                    }
                  }
                },
                "required": [
                  "steps"
                ],
                "additionalProperties": false
              },
              "example": {
                "steps": [
                  {
                    "channel": "email",
                    "wait_hours": 0,
                    "template": "Subject: Nurses for the summer\n\nHi {{first_name}}, …"
                  },
                  {
                    "channel": "sms",
                    "wait_hours": 48,
                    "template": "Hi {{first_name}}, did you see my email?"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replace a draft's sequence",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "campaign"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "draft, active, paused, completed, archived or needs_review."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "broadcast",
                        "sequence",
                        "multichannel"
                      ]
                    },
                    "channels": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The channel mix of the sequence, in order."
                    },
                    "step_count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "brand_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "schedule_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "steps": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      },
                      "description": "The sequence (the step shape above)."
                    },
                    "rules": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    },
                    "settings": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "The campaign's own settings override."
                    },
                    "stats": {
                      "type": "object",
                      "properties": {
                        "enrolled": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "in_progress": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "paused": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "completed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "replied": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "meetings_booked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "sent": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "delivered": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "opened": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "clicked": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "enrolled",
                        "in_progress",
                        "paused",
                        "completed",
                        "replied",
                        "meetings_booked",
                        "sent",
                        "delivered",
                        "opened",
                        "clicked"
                      ],
                      "additionalProperties": false,
                      "description": "The campaign's numbers right now."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "status",
                    "kind",
                    "channels",
                    "step_count",
                    "brand_id",
                    "schedule_at",
                    "created_at",
                    "steps",
                    "rules",
                    "settings",
                    "stats"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "object": "campaign",
                  "name": "Summer nurses — Stockholm",
                  "status": "draft",
                  "kind": "sequence",
                  "channels": [
                    "email",
                    "sms"
                  ],
                  "step_count": 2,
                  "brand_id": null,
                  "schedule_at": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "steps": [
                    {
                      "channel": "email",
                      "wait_hours": 0,
                      "template": "Subject: Nurses for the summer\n\nHi {{first_name}}, …"
                    },
                    {
                      "channel": "sms",
                      "wait_hours": 48,
                      "template": "Hi {{first_name}}, did you see my email?"
                    }
                  ],
                  "rules": [
                    {
                      "name": "Stop on reply",
                      "when": {
                        "event": "replied"
                      },
                      "then": {
                        "action": "pause"
                      }
                    }
                  ],
                  "settings": {
                    "approve_before_send": "manual"
                  },
                  "stats": {
                    "enrolled": 120,
                    "in_progress": 80,
                    "paused": 4,
                    "completed": 20,
                    "replied": 14,
                    "meetings_booked": 2,
                    "sent": 210,
                    "delivered": 204,
                    "opened": 96,
                    "clicked": 12
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:write",
        "x-norreach-action": "campaigns.edit",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/cards/{id}": {
      "get": {
        "operationId": "get_plan_card",
        "summary": "One plan card",
        "description": "One card of a plan: its words, why it is there, its state, what holds it and the claims in it that were checked.\n\nRequires the `plans:read` scope.",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One plan card",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "plan_card"
                    },
                    "plan_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "date": {
                      "type": "string"
                    },
                    "time_label": {
                      "type": "string"
                    },
                    "scheduled_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "channel": {
                      "type": "string"
                    },
                    "arc_stage": {
                      "type": "string",
                      "enum": [
                        "curiosity",
                        "awareness",
                        "consideration",
                        "proof",
                        "offer",
                        "urgency",
                        "decision"
                      ]
                    },
                    "title": {
                      "type": "string"
                    },
                    "what": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "The card's words, by kind: email (subject, body), message (text), post (caption), call (opening), ad (primary …)."
                    },
                    "why": {
                      "type": "string"
                    },
                    "chain": {
                      "type": "string"
                    },
                    "state": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "awaiting_approval",
                        "running",
                        "completed",
                        "skipped",
                        "failed"
                      ]
                    },
                    "conditional": {
                      "type": "boolean",
                      "description": "Fires on the lead's own behaviour rather than at a set time."
                    },
                    "cost_class": {
                      "type": "string",
                      "enum": [
                        "free",
                        "low",
                        "high",
                        "customer"
                      ]
                    },
                    "approved_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "hold": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "policy",
                            "claim",
                            "state"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Why it waits: policy (your plan's settings), claim (a claim needs checking — decide it in the app), state (the lead's own state)."
                    },
                    "claims": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "claim": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "flagged",
                              "sourced"
                            ]
                          },
                          "source": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "claim",
                          "status",
                          "source"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "outcome": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "note": {
                              "type": "string"
                            },
                            "metrics": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "label": {
                                    "type": "string"
                                  },
                                  "value": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "label",
                                  "value"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "note",
                            "metrics"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "plan_id",
                    "date",
                    "time_label",
                    "scheduled_at",
                    "channel",
                    "arc_stage",
                    "title",
                    "what",
                    "why",
                    "chain",
                    "state",
                    "conditional",
                    "cost_class",
                    "approved_at",
                    "hold",
                    "claims",
                    "outcome"
                  ],
                  "additionalProperties": false,
                  "description": "One card of a plan — one touch on one day."
                },
                "example": {
                  "id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                  "object": "plan_card",
                  "plan_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                  "date": "2026-11-12",
                  "time_label": "09:30",
                  "scheduled_at": null,
                  "channel": "email",
                  "arc_stage": "awareness",
                  "title": "Intro to clinic managers",
                  "what": {
                    "kind": "email",
                    "subject": "Nurses for the winter",
                    "body": "Hi {{first_name}}, …"
                  },
                  "why": "Clinic managers plan staffing a month ahead.",
                  "chain": "Opens feed the follow-up on day 4.",
                  "state": "awaiting_approval",
                  "conditional": false,
                  "cost_class": "free",
                  "approved_at": null,
                  "hold": "policy",
                  "claims": [],
                  "outcome": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_plan_card",
        "summary": "Change a card's words",
        "description": "Changes the words of a card that hasn't gone out: `subject` (email cards) and `body` (an email's body, a message's text, a post's caption, a call's opening, an ad's primary text), and optionally `why`. A call card keeps its AI disclosure whatever is sent. A card that is running or already ran can't change (409); a card held on a claim changes in the app, where the claim is decided (409).\n\nRequires the `plans:write` scope.",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "what": {
                    "type": "object",
                    "properties": {
                      "subject": {
                        "description": "Email cards: the subject line.",
                        "type": "string",
                        "maxLength": 300
                      },
                      "body": {
                        "description": "The words: an email's body, a message's text, a post's caption, a call's opening, an ad's primary text.",
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 20000
                      }
                    },
                    "additionalProperties": false
                  },
                  "why": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 600
                  }
                },
                "required": [
                  "what"
                ],
                "additionalProperties": false
              },
              "example": {
                "what": {
                  "subject": "Winter nurses — ready in 48 hours"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Change a card's words",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "plan_card"
                    },
                    "plan_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "date": {
                      "type": "string"
                    },
                    "time_label": {
                      "type": "string"
                    },
                    "scheduled_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "channel": {
                      "type": "string"
                    },
                    "arc_stage": {
                      "type": "string",
                      "enum": [
                        "curiosity",
                        "awareness",
                        "consideration",
                        "proof",
                        "offer",
                        "urgency",
                        "decision"
                      ]
                    },
                    "title": {
                      "type": "string"
                    },
                    "what": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "The card's words, by kind: email (subject, body), message (text), post (caption), call (opening), ad (primary …)."
                    },
                    "why": {
                      "type": "string"
                    },
                    "chain": {
                      "type": "string"
                    },
                    "state": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "awaiting_approval",
                        "running",
                        "completed",
                        "skipped",
                        "failed"
                      ]
                    },
                    "conditional": {
                      "type": "boolean",
                      "description": "Fires on the lead's own behaviour rather than at a set time."
                    },
                    "cost_class": {
                      "type": "string",
                      "enum": [
                        "free",
                        "low",
                        "high",
                        "customer"
                      ]
                    },
                    "approved_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "hold": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "policy",
                            "claim",
                            "state"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Why it waits: policy (your plan's settings), claim (a claim needs checking — decide it in the app), state (the lead's own state)."
                    },
                    "claims": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "claim": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "flagged",
                              "sourced"
                            ]
                          },
                          "source": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "claim",
                          "status",
                          "source"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "outcome": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "note": {
                              "type": "string"
                            },
                            "metrics": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "label": {
                                    "type": "string"
                                  },
                                  "value": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "label",
                                  "value"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "note",
                            "metrics"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "plan_id",
                    "date",
                    "time_label",
                    "scheduled_at",
                    "channel",
                    "arc_stage",
                    "title",
                    "what",
                    "why",
                    "chain",
                    "state",
                    "conditional",
                    "cost_class",
                    "approved_at",
                    "hold",
                    "claims",
                    "outcome"
                  ],
                  "additionalProperties": false,
                  "description": "One card of a plan — one touch on one day."
                },
                "example": {
                  "id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                  "object": "plan_card",
                  "plan_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                  "date": "2026-11-12",
                  "time_label": "09:30",
                  "scheduled_at": null,
                  "channel": "email",
                  "arc_stage": "awareness",
                  "title": "Intro to clinic managers",
                  "what": {
                    "kind": "email",
                    "subject": "Winter nurses — ready in 48 hours",
                    "body": "Hi {{first_name}}, …"
                  },
                  "why": "Clinic managers plan staffing a month ahead.",
                  "chain": "Opens feed the follow-up on day 4.",
                  "state": "awaiting_approval",
                  "conditional": false,
                  "cost_class": "free",
                  "approved_at": null,
                  "hold": "policy",
                  "claims": [],
                  "outcome": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:write",
        "x-norreach-action": "plan.edit",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/cards/{id}/approve": {
      "post": {
        "operationId": "approve_plan_card",
        "summary": "Approve a plan card",
        "description": "Says yes to a card waiting for a person, as the key's creator — it goes out when its time comes. The same deciding core as the Approvals page (so the key also needs approvals:decide): the outreach pause, the creator's role, the card re-read in this workspace. Optional `edits` change its words as it is approved. A card held on a claim → 409 conflict (decide the claim in the app); approving an approved card changes nothing (`count: 0`). `dry_run=true` checks it and changes nothing.\n\nRequires the `plans:approve` scope (reaches people, spends or publishes).",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:approve"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "edits": {
                    "type": "object",
                    "properties": {
                      "subject": {
                        "type": "string",
                        "maxLength": 300
                      },
                      "body": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 20000
                      }
                    },
                    "additionalProperties": false
                  }
                },
                "additionalProperties": false
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Approve a plan card",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "card_decision"
                    },
                    "card_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "decision": {
                      "type": "string",
                      "enum": [
                        "approve",
                        "skip"
                      ]
                    },
                    "status": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The card's state now (queued once approved, skipped) — dry_run on a dry run."
                    },
                    "count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "0 when nothing changed (it already was)."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "card_id",
                    "decision",
                    "status",
                    "count",
                    "note",
                    "dry_run"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "card_decision",
                  "card_id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                  "decision": "approve",
                  "status": "queued",
                  "count": 1,
                  "note": "Approved — it goes out when its time comes.",
                  "dry_run": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace. · `already_decided` — Already handled.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:approve",
        "x-norreach-action": "plan.approve",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/cards/{id}/skip": {
      "post": {
        "operationId": "skip_plan_card",
        "summary": "Skip a plan card",
        "description": "Says no to a card: it stays in the plan, struck out, and never goes out. The same deciding core as the Approvals page (the key also needs approvals:decide). A card that is running or already ran can't be skipped (409).\n\nRequires the `plans:approve` scope (reaches people, spends or publishes).",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:approve"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Skip a plan card",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "card_decision"
                    },
                    "card_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "decision": {
                      "type": "string",
                      "enum": [
                        "approve",
                        "skip"
                      ]
                    },
                    "status": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The card's state now (queued once approved, skipped) — dry_run on a dry run."
                    },
                    "count": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "0 when nothing changed (it already was)."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "card_id",
                    "decision",
                    "status",
                    "count",
                    "note",
                    "dry_run"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "card_decision",
                  "card_id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                  "decision": "skip",
                  "status": "skipped",
                  "count": 1,
                  "note": "Skipped — the card stays in your plan, struck out.",
                  "dry_run": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace. · `already_decided` — Already handled.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:approve",
        "x-norreach-action": "plan.approve",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/companies": {
      "get": {
        "operationId": "list_companies",
        "summary": "List companies",
        "description": "The companies your contacts work at, with how many contacts each — derived from the contacts' company field (there are no separate company records): spellings that differ only in case or spacing are one company, named the way most contacts name it. Most contacts first. `q` narrows to companies whose name contains it. Counts cover the newest 20 000 contacts with a company (`counts_capped` says when there are more).\n\nRequires the `contacts:read` scope.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Part of the company's name.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List companies",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "const": "company"
                          },
                          "name": {
                            "type": "string",
                            "description": "The company as your contacts name it."
                          },
                          "contacts": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "Contacts at this company."
                          }
                        },
                        "required": [
                          "object",
                          "name",
                          "contacts"
                        ],
                        "additionalProperties": false,
                        "description": "A company your contacts work at (derived from the contacts' company field — there are no separate company records)."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "counts_capped": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor",
                    "counts_capped"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "company",
                      "name": "Karolinska Care",
                      "contacts": 14
                    },
                    {
                      "object": "company",
                      "name": "Nordic Dental",
                      "contacts": 6
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null,
                  "counts_capped": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/contacts": {
      "get": {
        "operationId": "list_contacts",
        "summary": "List contacts",
        "description": "The workspace's contacts, newest first, a page at a time. Filter by text (`q` searches names, email, company and phone), tag, list, source, status, stage, owner or dates.\n\nRequires the `contacts:read` scope.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Text search.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 50
            }
          },
          {
            "name": "list_id",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 40
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "contacted",
                "interested",
                "not_interested",
                "converted",
                "meeting_booked",
                "bad_data",
                "bad_timing",
                "neutral",
                "unresponsive",
                "unqualified",
                "dnc"
              ]
            }
          },
          {
            "name": "stage",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "contacted",
                "meeting",
                "qualified",
                "won",
                "lost"
              ]
            }
          },
          {
            "name": "assigned_to",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "created_after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "created_before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "updated_after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "default": "-created_at",
              "type": "string",
              "enum": [
                "created_at",
                "-created_at",
                "updated_at",
                "-updated_at"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List contacts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "contact"
                          },
                          "first_name": {
                            "type": "string"
                          },
                          "last_name": {
                            "type": "string"
                          },
                          "email": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "phone": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "E.164, e.g. +46701234567."
                          },
                          "company": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "title": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "type": "string",
                            "description": "One of: new, contacted, interested, not_interested, converted, meeting_booked, bad_data, bad_timing, neutral, unresponsive, unqualified, dnc."
                          },
                          "stage": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Pipeline stage — one of: new, contacted, meeting, qualified, won, lost."
                          },
                          "tags": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "source": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Where the contact came from (`api` for contacts created through the API)."
                          },
                          "assigned_to": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The member who owns this contact."
                          },
                          "timezone": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "IANA time zone — quiet hours follow it."
                          },
                          "linkedin_url": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "fit_score": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "consent": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "basis": {
                                    "type": "string",
                                    "enum": [
                                      "legitimate_interest",
                                      "consent",
                                      "contract"
                                    ],
                                    "description": "The lawful basis for contacting this person. Without one, nothing is sent to them."
                                  },
                                  "source": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "maxLength": 80
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ],
                                    "description": "Where the basis came from (e.g. `crm_import`, `webinar_signup`)."
                                  },
                                  "recorded_at": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "description": "RFC 3339 UTC timestamp with milliseconds."
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  }
                                },
                                "required": [
                                  "basis",
                                  "source",
                                  "recorded_at"
                                ],
                                "additionalProperties": false,
                                "description": "The recorded lawful basis, or null when none is recorded."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "attrs": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {},
                            "description": "Your own fields (free-form JSON, at most 16 KB)."
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "updated_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "first_name",
                          "last_name",
                          "email",
                          "phone",
                          "company",
                          "title",
                          "status",
                          "stage",
                          "tags",
                          "source",
                          "assigned_to",
                          "timezone",
                          "linkedin_url",
                          "fit_score",
                          "consent",
                          "attrs",
                          "created_at",
                          "updated_at"
                        ],
                        "additionalProperties": false,
                        "description": "A person you may reach."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                      "object": "contact",
                      "first_name": "Maja",
                      "last_name": "Lind",
                      "email": "maja.lind@example.com",
                      "phone": "+46701234567",
                      "company": "Example Care AB",
                      "title": "Head of Staffing",
                      "status": "new",
                      "stage": "new",
                      "tags": [
                        "webinar"
                      ],
                      "source": "api",
                      "assigned_to": null,
                      "timezone": "Europe/Stockholm",
                      "linkedin_url": null,
                      "fit_score": null,
                      "consent": {
                        "basis": "consent",
                        "source": "webinar_signup",
                        "recorded_at": "2026-11-04T09:12:33.120Z"
                      },
                      "attrs": {
                        "crm_id": "C-1042"
                      },
                      "created_at": "2026-11-04T09:12:33.120Z",
                      "updated_at": "2026-11-04T09:12:33.120Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "create_contact",
        "summary": "Create a contact",
        "description": "Adds a person. Send `consent` with the lawful basis you hold — without one the contact is saved but nothing is ever sent to them. With `upsert_on` an existing contact with the same email (or phone) is updated instead (200). Automations that start on a new contact run as they do for contacts added in the app.\n\nRequires the `contacts:write` scope.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "first_name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "last_name": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "email": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 254,
                        "format": "email",
                        "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "phone": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 32
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Any common format; stored as E.164. Needs a country code."
                  },
                  "company": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "title": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "new",
                      "contacted",
                      "interested",
                      "not_interested",
                      "converted",
                      "meeting_booked",
                      "bad_data",
                      "bad_timing",
                      "neutral",
                      "unresponsive",
                      "unqualified",
                      "dnc"
                    ]
                  },
                  "stage": {
                    "type": "string",
                    "enum": [
                      "new",
                      "contacted",
                      "meeting",
                      "qualified",
                      "won",
                      "lost"
                    ]
                  },
                  "tags": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 50
                    }
                  },
                  "assigned_to": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "timezone": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 64
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "linkedin_url": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 500,
                        "format": "uri"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "attrs": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  },
                  "source": {
                    "description": "Where the contact came from (lowercase letters, digits and _). Defaults to `api`.",
                    "type": "string",
                    "pattern": "^[a-z0-9_]{1,40}$"
                  },
                  "consent": {
                    "description": "The lawful basis for contacting them. Without it the contact is saved but nothing is sent to them.",
                    "type": "object",
                    "properties": {
                      "basis": {
                        "type": "string",
                        "enum": [
                          "legitimate_interest",
                          "consent",
                          "contract"
                        ]
                      },
                      "source": {
                        "description": "Where the basis came from. Defaults to `api`.",
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 80
                      }
                    },
                    "required": [
                      "basis"
                    ],
                    "additionalProperties": false
                  },
                  "upsert_on": {
                    "description": "Update the existing contact with this email (or phone) instead of failing with a conflict.",
                    "type": "string",
                    "enum": [
                      "email",
                      "phone"
                    ]
                  }
                },
                "required": [
                  "first_name"
                ],
                "additionalProperties": false,
                "description": "A new contact."
              },
              "example": {
                "first_name": "Maja",
                "last_name": "Lind",
                "email": "maja.lind@example.com",
                "phone": "+46 70 123 45 67",
                "company": "Example Care AB",
                "tags": [
                  "webinar"
                ],
                "consent": {
                  "basis": "consent",
                  "source": "webinar_signup"
                },
                "upsert_on": "email"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Create a contact",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "contact"
                    },
                    "first_name": {
                      "type": "string"
                    },
                    "last_name": {
                      "type": "string"
                    },
                    "email": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "phone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "E.164, e.g. +46701234567."
                    },
                    "company": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "title": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string",
                      "description": "One of: new, contacted, interested, not_interested, converted, meeting_booked, bad_data, bad_timing, neutral, unresponsive, unqualified, dnc."
                    },
                    "stage": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Pipeline stage — one of: new, contacted, meeting, qualified, won, lost."
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "source": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Where the contact came from (`api` for contacts created through the API)."
                    },
                    "assigned_to": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The member who owns this contact."
                    },
                    "timezone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "IANA time zone — quiet hours follow it."
                    },
                    "linkedin_url": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fit_score": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "consent": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "basis": {
                              "type": "string",
                              "enum": [
                                "legitimate_interest",
                                "consent",
                                "contract"
                              ],
                              "description": "The lawful basis for contacting this person. Without one, nothing is sent to them."
                            },
                            "source": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 80
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Where the basis came from (e.g. `crm_import`, `webinar_signup`)."
                            },
                            "recorded_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "basis",
                            "source",
                            "recorded_at"
                          ],
                          "additionalProperties": false,
                          "description": "The recorded lawful basis, or null when none is recorded."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attrs": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "Your own fields (free-form JSON, at most 16 KB)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "first_name",
                    "last_name",
                    "email",
                    "phone",
                    "company",
                    "title",
                    "status",
                    "stage",
                    "tags",
                    "source",
                    "assigned_to",
                    "timezone",
                    "linkedin_url",
                    "fit_score",
                    "consent",
                    "attrs",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "A person you may reach."
                },
                "example": {
                  "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "object": "contact",
                  "first_name": "Maja",
                  "last_name": "Lind",
                  "email": "maja.lind@example.com",
                  "phone": "+46701234567",
                  "company": "Example Care AB",
                  "title": "Head of Staffing",
                  "status": "new",
                  "stage": "new",
                  "tags": [
                    "webinar"
                  ],
                  "source": "api",
                  "assigned_to": null,
                  "timezone": "Europe/Stockholm",
                  "linkedin_url": null,
                  "fit_score": null,
                  "consent": {
                    "basis": "consent",
                    "source": "webinar_signup",
                    "recorded_at": "2026-11-04T09:12:33.120Z"
                  },
                  "attrs": {
                    "crm_id": "C-1042"
                  },
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:write",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/contacts/{id}": {
      "delete": {
        "operationId": "erase_contact",
        "summary": "Erase a contact",
        "description": "Erases the person: the contact, their conversations, messages, timeline, form submissions and ad leads are deleted, and their details are cleared from calls, meetings and deals. Only a fingerprint of their email and phone is kept as a do-not-contact entry, so they are never contacted again — even if they are added again later. This can't be undone. Use `dry_run=true` to see what would go.\n\nRequires the `contacts:delete` scope (reaches people, spends or publishes).",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:delete"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erase a contact",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "erasure"
                    },
                    "contact_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "erased": {
                      "type": "boolean",
                      "description": "false on a dry run."
                    },
                    "do_not_contact_kept": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "email",
                          "phone"
                        ]
                      },
                      "description": "Which fingerprints were kept so the person is never contacted again."
                    },
                    "removed": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      "description": "What was removed or cleared, by kind."
                    }
                  },
                  "required": [
                    "object",
                    "contact_id",
                    "erased",
                    "do_not_contact_kept",
                    "removed"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "erasure",
                  "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "erased": true,
                  "do_not_contact_kept": [
                    "email",
                    "phone"
                  ],
                  "removed": {
                    "contact": 1,
                    "messages": 6,
                    "threads": 2,
                    "linkedin_tasks": 0,
                    "events": 14,
                    "lp_submissions": 1,
                    "meta_leads": 0,
                    "calls": 1,
                    "meetings": 1,
                    "plan_prospects": 0,
                    "deals": 0,
                    "suppression_replaced": 0
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:delete",
        "x-norreach-action": "settings.compliance",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      },
      "get": {
        "operationId": "get_contact",
        "summary": "One contact",
        "description": "A contact with its tags, consent, stage and the lists it is on.\n\nRequires the `contacts:read` scope.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One contact",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "contact"
                    },
                    "first_name": {
                      "type": "string"
                    },
                    "last_name": {
                      "type": "string"
                    },
                    "email": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "phone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "E.164, e.g. +46701234567."
                    },
                    "company": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "title": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string",
                      "description": "One of: new, contacted, interested, not_interested, converted, meeting_booked, bad_data, bad_timing, neutral, unresponsive, unqualified, dnc."
                    },
                    "stage": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Pipeline stage — one of: new, contacted, meeting, qualified, won, lost."
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "source": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Where the contact came from (`api` for contacts created through the API)."
                    },
                    "assigned_to": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The member who owns this contact."
                    },
                    "timezone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "IANA time zone — quiet hours follow it."
                    },
                    "linkedin_url": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fit_score": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "consent": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "basis": {
                              "type": "string",
                              "enum": [
                                "legitimate_interest",
                                "consent",
                                "contract"
                              ],
                              "description": "The lawful basis for contacting this person. Without one, nothing is sent to them."
                            },
                            "source": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 80
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Where the basis came from (e.g. `crm_import`, `webinar_signup`)."
                            },
                            "recorded_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "basis",
                            "source",
                            "recorded_at"
                          ],
                          "additionalProperties": false,
                          "description": "The recorded lawful basis, or null when none is recorded."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attrs": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "Your own fields (free-form JSON, at most 16 KB)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "lists": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "name": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "name"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Lists the contact is on."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "first_name",
                    "last_name",
                    "email",
                    "phone",
                    "company",
                    "title",
                    "status",
                    "stage",
                    "tags",
                    "source",
                    "assigned_to",
                    "timezone",
                    "linkedin_url",
                    "fit_score",
                    "consent",
                    "attrs",
                    "created_at",
                    "updated_at",
                    "lists"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "object": "contact",
                  "first_name": "Maja",
                  "last_name": "Lind",
                  "email": "maja.lind@example.com",
                  "phone": "+46701234567",
                  "company": "Example Care AB",
                  "title": "Head of Staffing",
                  "status": "new",
                  "stage": "new",
                  "tags": [
                    "webinar"
                  ],
                  "source": "api",
                  "assigned_to": null,
                  "timezone": "Europe/Stockholm",
                  "linkedin_url": null,
                  "fit_score": null,
                  "consent": {
                    "basis": "consent",
                    "source": "webinar_signup",
                    "recorded_at": "2026-11-04T09:12:33.120Z"
                  },
                  "attrs": {
                    "crm_id": "C-1042"
                  },
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T09:12:33.120Z",
                  "lists": [
                    {
                      "id": "9b2f7e1d-3c4a-4b5d-8e6f-7a8b9c0d1e2f",
                      "name": "Webinar November"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_contact",
        "summary": "Update a contact",
        "description": "Changes the fields you send; the rest stay as they are. Consent (`PUT /contacts/{id}/consent`) and stage (`POST /contacts/{id}/stage`) have their own operations.\n\nRequires the `contacts:write` scope.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "first_name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "last_name": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "email": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 254,
                        "format": "email",
                        "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "phone": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 32
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Any common format; stored as E.164. Needs a country code."
                  },
                  "company": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "title": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "new",
                      "contacted",
                      "interested",
                      "not_interested",
                      "converted",
                      "meeting_booked",
                      "bad_data",
                      "bad_timing",
                      "neutral",
                      "unresponsive",
                      "unqualified",
                      "dnc"
                    ]
                  },
                  "tags": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 50
                    }
                  },
                  "assigned_to": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "timezone": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 64
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "linkedin_url": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 500,
                        "format": "uri"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "attrs": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "additionalProperties": false,
                "description": "Fields to change. Omitted fields stay as they are; consent and stage have their own operations."
              },
              "example": {
                "title": "Staffing Director",
                "tags": [
                  "webinar",
                  "vip"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Update a contact",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "contact"
                    },
                    "first_name": {
                      "type": "string"
                    },
                    "last_name": {
                      "type": "string"
                    },
                    "email": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "phone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "E.164, e.g. +46701234567."
                    },
                    "company": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "title": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string",
                      "description": "One of: new, contacted, interested, not_interested, converted, meeting_booked, bad_data, bad_timing, neutral, unresponsive, unqualified, dnc."
                    },
                    "stage": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Pipeline stage — one of: new, contacted, meeting, qualified, won, lost."
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "source": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Where the contact came from (`api` for contacts created through the API)."
                    },
                    "assigned_to": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The member who owns this contact."
                    },
                    "timezone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "IANA time zone — quiet hours follow it."
                    },
                    "linkedin_url": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fit_score": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "consent": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "basis": {
                              "type": "string",
                              "enum": [
                                "legitimate_interest",
                                "consent",
                                "contract"
                              ],
                              "description": "The lawful basis for contacting this person. Without one, nothing is sent to them."
                            },
                            "source": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 80
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Where the basis came from (e.g. `crm_import`, `webinar_signup`)."
                            },
                            "recorded_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "basis",
                            "source",
                            "recorded_at"
                          ],
                          "additionalProperties": false,
                          "description": "The recorded lawful basis, or null when none is recorded."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attrs": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "Your own fields (free-form JSON, at most 16 KB)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "first_name",
                    "last_name",
                    "email",
                    "phone",
                    "company",
                    "title",
                    "status",
                    "stage",
                    "tags",
                    "source",
                    "assigned_to",
                    "timezone",
                    "linkedin_url",
                    "fit_score",
                    "consent",
                    "attrs",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "A person you may reach."
                },
                "example": {
                  "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "object": "contact",
                  "first_name": "Maja",
                  "last_name": "Lind",
                  "email": "maja.lind@example.com",
                  "phone": "+46701234567",
                  "company": "Example Care AB",
                  "title": "Staffing Director",
                  "status": "new",
                  "stage": "new",
                  "tags": [
                    "webinar",
                    "vip"
                  ],
                  "source": "api",
                  "assigned_to": null,
                  "timezone": "Europe/Stockholm",
                  "linkedin_url": null,
                  "fit_score": null,
                  "consent": {
                    "basis": "consent",
                    "source": "webinar_signup",
                    "recorded_at": "2026-11-04T09:12:33.120Z"
                  },
                  "attrs": {
                    "crm_id": "C-1042"
                  },
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:write",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/contacts/{id}/consent": {
      "put": {
        "operationId": "set_contact_consent",
        "summary": "Set the lawful basis",
        "description": "Records the lawful basis for contacting this person (`basis: null` clears it — nothing is sent to them after that). Recording a basis lets sequences that were waiting for one carry on, exactly as setting it in the app does.\n\nRequires the `contacts:write` scope.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "basis": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "legitimate_interest",
                          "consent",
                          "contract"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "source": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  }
                },
                "required": [
                  "basis"
                ],
                "additionalProperties": false
              },
              "example": {
                "basis": "consent",
                "source": "double_opt_in"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Set the lawful basis",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "contact"
                    },
                    "first_name": {
                      "type": "string"
                    },
                    "last_name": {
                      "type": "string"
                    },
                    "email": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "phone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "E.164, e.g. +46701234567."
                    },
                    "company": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "title": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string",
                      "description": "One of: new, contacted, interested, not_interested, converted, meeting_booked, bad_data, bad_timing, neutral, unresponsive, unqualified, dnc."
                    },
                    "stage": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Pipeline stage — one of: new, contacted, meeting, qualified, won, lost."
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "source": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Where the contact came from (`api` for contacts created through the API)."
                    },
                    "assigned_to": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The member who owns this contact."
                    },
                    "timezone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "IANA time zone — quiet hours follow it."
                    },
                    "linkedin_url": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fit_score": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "consent": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "basis": {
                              "type": "string",
                              "enum": [
                                "legitimate_interest",
                                "consent",
                                "contract"
                              ],
                              "description": "The lawful basis for contacting this person. Without one, nothing is sent to them."
                            },
                            "source": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 80
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Where the basis came from (e.g. `crm_import`, `webinar_signup`)."
                            },
                            "recorded_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "basis",
                            "source",
                            "recorded_at"
                          ],
                          "additionalProperties": false,
                          "description": "The recorded lawful basis, or null when none is recorded."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attrs": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "Your own fields (free-form JSON, at most 16 KB)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "first_name",
                    "last_name",
                    "email",
                    "phone",
                    "company",
                    "title",
                    "status",
                    "stage",
                    "tags",
                    "source",
                    "assigned_to",
                    "timezone",
                    "linkedin_url",
                    "fit_score",
                    "consent",
                    "attrs",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "A person you may reach."
                },
                "example": {
                  "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "object": "contact",
                  "first_name": "Maja",
                  "last_name": "Lind",
                  "email": "maja.lind@example.com",
                  "phone": "+46701234567",
                  "company": "Example Care AB",
                  "title": "Head of Staffing",
                  "status": "new",
                  "stage": "new",
                  "tags": [
                    "webinar"
                  ],
                  "source": "api",
                  "assigned_to": null,
                  "timezone": "Europe/Stockholm",
                  "linkedin_url": null,
                  "fit_score": null,
                  "consent": {
                    "basis": "consent",
                    "source": "webinar_signup",
                    "recorded_at": "2026-11-04T09:12:33.120Z"
                  },
                  "attrs": {
                    "crm_id": "C-1042"
                  },
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:write",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/contacts/{id}/leads": {
      "get": {
        "operationId": "list_contact_leads",
        "summary": "A contact's form leads",
        "description": "The landing-page forms this contact filled in, newest first (up to 50, spam left out).\n\nRequires the `pages:read` scope.",
        "tags": [
          "Contacts",
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A contact's form leads",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "lead"
                          },
                          "page_id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "contact_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "network": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The ad network the visitor came from, if any."
                          },
                          "ad_key": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "campaign": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "marketing_opt_in": {
                            "type": "string",
                            "enum": [
                              "yes",
                              "no",
                              "not_asked"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "email": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "phone": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "answers": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "key": {
                                  "type": "string"
                                },
                                "label": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "value": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "boolean"
                                    }
                                  ]
                                }
                              },
                              "required": [
                                "key",
                                "label",
                                "value"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "page_title": {
                            "type": "string"
                          },
                          "page_url": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "page_id",
                          "contact_id",
                          "status",
                          "created_at",
                          "network",
                          "ad_key",
                          "campaign",
                          "marketing_opt_in",
                          "name",
                          "email",
                          "phone",
                          "answers",
                          "page_title",
                          "page_url"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "6b7c8d9e-0f1a-4b2c-9d3e-4f5a6b7c8d9e",
                      "object": "lead",
                      "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                      "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                      "status": "new",
                      "created_at": "2026-11-04T09:12:33.120Z",
                      "network": "meta",
                      "ad_key": null,
                      "campaign": "november",
                      "marketing_opt_in": "yes",
                      "name": "Maja Lind",
                      "email": "maja.lind@example.com",
                      "phone": null,
                      "answers": [
                        {
                          "key": "role",
                          "label": "Role",
                          "value": "Nurse"
                        }
                      ],
                      "page_title": "Nurses when you need them",
                      "page_url": "https://acme.norreach.page/nurses-stockholm"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/contacts/{id}/notes": {
      "post": {
        "operationId": "add_contact_note",
        "summary": "Add a note",
        "description": "Adds a note to the contact (newest on top) and to their timeline, as a note added in the app.\n\nRequires the `contacts:write` scope.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 5000
                  }
                },
                "required": [
                  "text"
                ],
                "additionalProperties": false
              },
              "example": {
                "text": "Asked for pricing for 12 nurses in January."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Add a note",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "note"
                    },
                    "contact_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "text": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "object",
                    "contact_id",
                    "text",
                    "created_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "note",
                  "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "text": "Asked for pricing for 12 nurses in January.",
                  "created_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:write",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/contacts/{id}/stage": {
      "post": {
        "operationId": "set_contact_stage",
        "summary": "Move to a stage",
        "description": "Moves the contact to a pipeline stage (new, contacted, meeting, qualified, won, lost) and records the move on their timeline.\n\nRequires the `contacts:write` scope.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "stage": {
                    "type": "string",
                    "enum": [
                      "new",
                      "contacted",
                      "meeting",
                      "qualified",
                      "won",
                      "lost"
                    ]
                  }
                },
                "required": [
                  "stage"
                ],
                "additionalProperties": false
              },
              "example": {
                "stage": "meeting"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Move to a stage",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "contact"
                    },
                    "first_name": {
                      "type": "string"
                    },
                    "last_name": {
                      "type": "string"
                    },
                    "email": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "phone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "E.164, e.g. +46701234567."
                    },
                    "company": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "title": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string",
                      "description": "One of: new, contacted, interested, not_interested, converted, meeting_booked, bad_data, bad_timing, neutral, unresponsive, unqualified, dnc."
                    },
                    "stage": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Pipeline stage — one of: new, contacted, meeting, qualified, won, lost."
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "source": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Where the contact came from (`api` for contacts created through the API)."
                    },
                    "assigned_to": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The member who owns this contact."
                    },
                    "timezone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "IANA time zone — quiet hours follow it."
                    },
                    "linkedin_url": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fit_score": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "consent": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "basis": {
                              "type": "string",
                              "enum": [
                                "legitimate_interest",
                                "consent",
                                "contract"
                              ],
                              "description": "The lawful basis for contacting this person. Without one, nothing is sent to them."
                            },
                            "source": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 80
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Where the basis came from (e.g. `crm_import`, `webinar_signup`)."
                            },
                            "recorded_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "basis",
                            "source",
                            "recorded_at"
                          ],
                          "additionalProperties": false,
                          "description": "The recorded lawful basis, or null when none is recorded."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attrs": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "Your own fields (free-form JSON, at most 16 KB)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "first_name",
                    "last_name",
                    "email",
                    "phone",
                    "company",
                    "title",
                    "status",
                    "stage",
                    "tags",
                    "source",
                    "assigned_to",
                    "timezone",
                    "linkedin_url",
                    "fit_score",
                    "consent",
                    "attrs",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "A person you may reach."
                },
                "example": {
                  "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "object": "contact",
                  "first_name": "Maja",
                  "last_name": "Lind",
                  "email": "maja.lind@example.com",
                  "phone": "+46701234567",
                  "company": "Example Care AB",
                  "title": "Head of Staffing",
                  "status": "new",
                  "stage": "meeting",
                  "tags": [
                    "webinar"
                  ],
                  "source": "api",
                  "assigned_to": null,
                  "timezone": "Europe/Stockholm",
                  "linkedin_url": null,
                  "fit_score": null,
                  "consent": {
                    "basis": "consent",
                    "source": "webinar_signup",
                    "recorded_at": "2026-11-04T09:12:33.120Z"
                  },
                  "attrs": {
                    "crm_id": "C-1042"
                  },
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:write",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/contacts/{id}/tags/{tag}": {
      "delete": {
        "operationId": "remove_contact_tag",
        "summary": "Untag a contact",
        "description": "Removes a tag (URL-encode it in the path). Removing a tag the contact doesn't have changes nothing.\n\nRequires the `contacts:write` scope.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "tag",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Untag a contact",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "contact"
                    },
                    "first_name": {
                      "type": "string"
                    },
                    "last_name": {
                      "type": "string"
                    },
                    "email": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "phone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "E.164, e.g. +46701234567."
                    },
                    "company": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "title": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string",
                      "description": "One of: new, contacted, interested, not_interested, converted, meeting_booked, bad_data, bad_timing, neutral, unresponsive, unqualified, dnc."
                    },
                    "stage": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Pipeline stage — one of: new, contacted, meeting, qualified, won, lost."
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "source": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Where the contact came from (`api` for contacts created through the API)."
                    },
                    "assigned_to": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The member who owns this contact."
                    },
                    "timezone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "IANA time zone — quiet hours follow it."
                    },
                    "linkedin_url": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fit_score": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "consent": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "basis": {
                              "type": "string",
                              "enum": [
                                "legitimate_interest",
                                "consent",
                                "contract"
                              ],
                              "description": "The lawful basis for contacting this person. Without one, nothing is sent to them."
                            },
                            "source": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 80
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Where the basis came from (e.g. `crm_import`, `webinar_signup`)."
                            },
                            "recorded_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "basis",
                            "source",
                            "recorded_at"
                          ],
                          "additionalProperties": false,
                          "description": "The recorded lawful basis, or null when none is recorded."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attrs": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "Your own fields (free-form JSON, at most 16 KB)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "first_name",
                    "last_name",
                    "email",
                    "phone",
                    "company",
                    "title",
                    "status",
                    "stage",
                    "tags",
                    "source",
                    "assigned_to",
                    "timezone",
                    "linkedin_url",
                    "fit_score",
                    "consent",
                    "attrs",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "A person you may reach."
                },
                "example": {
                  "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "object": "contact",
                  "first_name": "Maja",
                  "last_name": "Lind",
                  "email": "maja.lind@example.com",
                  "phone": "+46701234567",
                  "company": "Example Care AB",
                  "title": "Head of Staffing",
                  "status": "new",
                  "stage": "new",
                  "tags": [],
                  "source": "api",
                  "assigned_to": null,
                  "timezone": "Europe/Stockholm",
                  "linkedin_url": null,
                  "fit_score": null,
                  "consent": {
                    "basis": "consent",
                    "source": "webinar_signup",
                    "recorded_at": "2026-11-04T09:12:33.120Z"
                  },
                  "attrs": {
                    "crm_id": "C-1042"
                  },
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:write",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "add_contact_tag",
        "summary": "Tag a contact",
        "description": "Adds a tag (URL-encode it in the path). Adding a tag the contact already has changes nothing. Automations that start on a tag run as they do in the app.\n\nRequires the `contacts:write` scope.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "tag",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tag a contact",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "contact"
                    },
                    "first_name": {
                      "type": "string"
                    },
                    "last_name": {
                      "type": "string"
                    },
                    "email": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "phone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "E.164, e.g. +46701234567."
                    },
                    "company": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "title": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string",
                      "description": "One of: new, contacted, interested, not_interested, converted, meeting_booked, bad_data, bad_timing, neutral, unresponsive, unqualified, dnc."
                    },
                    "stage": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Pipeline stage — one of: new, contacted, meeting, qualified, won, lost."
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "source": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Where the contact came from (`api` for contacts created through the API)."
                    },
                    "assigned_to": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The member who owns this contact."
                    },
                    "timezone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "IANA time zone — quiet hours follow it."
                    },
                    "linkedin_url": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fit_score": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "consent": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "basis": {
                              "type": "string",
                              "enum": [
                                "legitimate_interest",
                                "consent",
                                "contract"
                              ],
                              "description": "The lawful basis for contacting this person. Without one, nothing is sent to them."
                            },
                            "source": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 80
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Where the basis came from (e.g. `crm_import`, `webinar_signup`)."
                            },
                            "recorded_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "basis",
                            "source",
                            "recorded_at"
                          ],
                          "additionalProperties": false,
                          "description": "The recorded lawful basis, or null when none is recorded."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attrs": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "Your own fields (free-form JSON, at most 16 KB)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "first_name",
                    "last_name",
                    "email",
                    "phone",
                    "company",
                    "title",
                    "status",
                    "stage",
                    "tags",
                    "source",
                    "assigned_to",
                    "timezone",
                    "linkedin_url",
                    "fit_score",
                    "consent",
                    "attrs",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "A person you may reach."
                },
                "example": {
                  "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "object": "contact",
                  "first_name": "Maja",
                  "last_name": "Lind",
                  "email": "maja.lind@example.com",
                  "phone": "+46701234567",
                  "company": "Example Care AB",
                  "title": "Head of Staffing",
                  "status": "new",
                  "stage": "new",
                  "tags": [
                    "webinar",
                    "vip"
                  ],
                  "source": "api",
                  "assigned_to": null,
                  "timezone": "Europe/Stockholm",
                  "linkedin_url": null,
                  "fit_score": null,
                  "consent": {
                    "basis": "consent",
                    "source": "webinar_signup",
                    "recorded_at": "2026-11-04T09:12:33.120Z"
                  },
                  "attrs": {
                    "crm_id": "C-1042"
                  },
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:write",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/contacts/batch": {
      "post": {
        "operationId": "batch_contacts",
        "summary": "Create or update many contacts",
        "description": "Up to 100 contacts in one request, each exactly like `POST /contacts` (use `upsert_on` to update existing ones). Each row succeeds or fails on its own; the answer lists them in order.\n\nRequires the `contacts:write` scope.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contacts": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "first_name": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 100
                        },
                        "last_name": {
                          "type": "string",
                          "maxLength": 100
                        },
                        "email": {
                          "anyOf": [
                            {
                              "type": "string",
                              "maxLength": 254,
                              "format": "email",
                              "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "phone": {
                          "anyOf": [
                            {
                              "type": "string",
                              "maxLength": 32
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Any common format; stored as E.164. Needs a country code."
                        },
                        "company": {
                          "anyOf": [
                            {
                              "type": "string",
                              "maxLength": 200
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "title": {
                          "anyOf": [
                            {
                              "type": "string",
                              "maxLength": 200
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "new",
                            "contacted",
                            "interested",
                            "not_interested",
                            "converted",
                            "meeting_booked",
                            "bad_data",
                            "bad_timing",
                            "neutral",
                            "unresponsive",
                            "unqualified",
                            "dnc"
                          ]
                        },
                        "stage": {
                          "type": "string",
                          "enum": [
                            "new",
                            "contacted",
                            "meeting",
                            "qualified",
                            "won",
                            "lost"
                          ]
                        },
                        "tags": {
                          "maxItems": 50,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 50
                          }
                        },
                        "assigned_to": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "timezone": {
                          "anyOf": [
                            {
                              "type": "string",
                              "maxLength": 64
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "linkedin_url": {
                          "anyOf": [
                            {
                              "type": "string",
                              "maxLength": 500,
                              "format": "uri"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "attrs": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        },
                        "source": {
                          "description": "Where the contact came from (lowercase letters, digits and _). Defaults to `api`.",
                          "type": "string",
                          "pattern": "^[a-z0-9_]{1,40}$"
                        },
                        "consent": {
                          "description": "The lawful basis for contacting them. Without it the contact is saved but nothing is sent to them.",
                          "type": "object",
                          "properties": {
                            "basis": {
                              "type": "string",
                              "enum": [
                                "legitimate_interest",
                                "consent",
                                "contract"
                              ]
                            },
                            "source": {
                              "description": "Where the basis came from. Defaults to `api`.",
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 80
                            }
                          },
                          "required": [
                            "basis"
                          ],
                          "additionalProperties": false
                        },
                        "upsert_on": {
                          "description": "Update the existing contact with this email (or phone) instead of failing with a conflict.",
                          "type": "string",
                          "enum": [
                            "email",
                            "phone"
                          ]
                        }
                      },
                      "required": [
                        "first_name"
                      ],
                      "additionalProperties": false,
                      "description": "A new contact."
                    },
                    "description": "Up to 100 contacts, each like `POST /contacts`."
                  }
                },
                "required": [
                  "contacts"
                ],
                "additionalProperties": false,
                "description": "Several contacts at once."
              },
              "example": {
                "contacts": [
                  {
                    "first_name": "Maja",
                    "email": "maja.lind@example.com",
                    "upsert_on": "email"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Create or update many contacts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "batch_result"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "created",
                              "updated",
                              "failed"
                            ]
                          },
                          "id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "error": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "code": {
                                    "type": "string"
                                  },
                                  "message": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "code",
                                  "message"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "index",
                          "status",
                          "id",
                          "error"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "created": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "updated": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "failed": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "created",
                    "updated",
                    "failed"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "batch_result",
                  "data": [
                    {
                      "index": 0,
                      "status": "created",
                      "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                      "error": null
                    }
                  ],
                  "created": 1,
                  "updated": 0,
                  "failed": 0
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:write",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/credits": {
      "get": {
        "operationId": "get_credits",
        "summary": "Get the credit balance",
        "description": "The workspace's credit balance (the exact sum of every grant and charge), its plan and the credits the plan includes per month, and what was spent and granted over `from`–`to` (YYYY-MM-DD, UTC; default the last 30 days, at most 366), per action. Credits are whole numbers; `exact` keeps the fraction a per-minute charge can leave. Owners and admins.\n\nRequires the `billing:read` scope.",
        "tags": [
          "Credits"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "billing:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day (YYYY-MM-DD, UTC; default 29 days before `to`).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day (YYYY-MM-DD, UTC; default today).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get the credit balance",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "credits"
                    },
                    "balance": {
                      "type": "object",
                      "properties": {
                        "credits": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Whole credits (rounded half away from zero)."
                        },
                        "exact": {
                          "type": "string",
                          "pattern": "^-?\\d+(?:\\.\\d{1,2})?$",
                          "description": "The exact amount as a decimal string — a per-minute charge can hold a fraction of a credit."
                        }
                      },
                      "required": [
                        "credits",
                        "exact"
                      ],
                      "additionalProperties": false,
                      "description": "What the workspace has now: the sum of every grant and charge."
                    },
                    "plan": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The workspace's plan (free, pro, enterprise), or null."
                    },
                    "monthly_allowance": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "credits": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "confirmed": {
                              "type": "boolean",
                              "description": "false = a default not confirmed for billing yet."
                            }
                          },
                          "required": [
                            "credits",
                            "confirmed"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Credits the plan includes per month."
                    },
                    "usage": {
                      "type": "object",
                      "properties": {
                        "from": {
                          "type": "string",
                          "description": "First day (YYYY-MM-DD, UTC)."
                        },
                        "to": {
                          "type": "string",
                          "description": "Last day (YYYY-MM-DD, UTC)."
                        },
                        "spent": {
                          "type": "object",
                          "properties": {
                            "credits": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Whole credits (rounded half away from zero)."
                            },
                            "exact": {
                              "type": "string",
                              "pattern": "^-?\\d+(?:\\.\\d{1,2})?$",
                              "description": "The exact amount as a decimal string — a per-minute charge can hold a fraction of a credit."
                            }
                          },
                          "required": [
                            "credits",
                            "exact"
                          ],
                          "additionalProperties": false,
                          "description": "An amount of credits."
                        },
                        "granted": {
                          "type": "object",
                          "properties": {
                            "credits": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Whole credits (rounded half away from zero)."
                            },
                            "exact": {
                              "type": "string",
                              "pattern": "^-?\\d+(?:\\.\\d{1,2})?$",
                              "description": "The exact amount as a decimal string — a per-minute charge can hold a fraction of a credit."
                            }
                          },
                          "required": [
                            "credits",
                            "exact"
                          ],
                          "additionalProperties": false,
                          "description": "An amount of credits."
                        },
                        "by_action": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "action": {
                                "type": "string",
                                "description": "What was charged (email.send, call.minute …)."
                              },
                              "label": {
                                "type": "string"
                              },
                              "spent": {
                                "type": "object",
                                "properties": {
                                  "credits": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Whole credits (rounded half away from zero)."
                                  },
                                  "exact": {
                                    "type": "string",
                                    "pattern": "^-?\\d+(?:\\.\\d{1,2})?$",
                                    "description": "The exact amount as a decimal string — a per-minute charge can hold a fraction of a credit."
                                  }
                                },
                                "required": [
                                  "credits",
                                  "exact"
                                ],
                                "additionalProperties": false,
                                "description": "An amount of credits."
                              },
                              "count": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991,
                                "description": "How many charges."
                              }
                            },
                            "required": [
                              "action",
                              "label",
                              "spent",
                              "count"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "truncated": {
                          "type": "boolean",
                          "description": "true when the period held more charges than were summed (20 000)."
                        }
                      },
                      "required": [
                        "from",
                        "to",
                        "spent",
                        "granted",
                        "by_action",
                        "truncated"
                      ],
                      "additionalProperties": false,
                      "description": "Spent and granted in the period."
                    }
                  },
                  "required": [
                    "object",
                    "balance",
                    "plan",
                    "monthly_allowance",
                    "usage"
                  ],
                  "additionalProperties": false,
                  "description": "The credit balance, the plan's allowance and the period's usage."
                },
                "example": {
                  "object": "credits",
                  "balance": {
                    "credits": 18431,
                    "exact": "18430.5"
                  },
                  "plan": "pro",
                  "monthly_allowance": {
                    "credits": 25000,
                    "confirmed": true
                  },
                  "usage": {
                    "from": "2026-10-07",
                    "to": "2026-11-05",
                    "spent": {
                      "credits": 6569,
                      "exact": "6569"
                    },
                    "granted": {
                      "credits": 25000,
                      "exact": "25000"
                    },
                    "by_action": [
                      {
                        "action": "call.minute",
                        "label": "AI call minutes",
                        "spent": {
                          "credits": 4104,
                          "exact": "4104"
                        },
                        "count": 120
                      },
                      {
                        "action": "email.send",
                        "label": "Emails sent",
                        "spent": {
                          "credits": 1830,
                          "exact": "1830"
                        },
                        "count": 1830
                      }
                    ],
                    "truncated": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "billing:read",
        "x-norreach-action": "billing.view",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/credits/ledger": {
      "get": {
        "operationId": "list_credit_ledger",
        "summary": "List the credit ledger",
        "description": "Every grant and charge, newest first: what was charged, how much (charges are negative), how many units (minutes, segments, actions) and what it was for when that is something the API knows (a call, a message, an ad launch …). Filter by `kind`, `action` and a day range (`from` / `to`, UTC, at most 366 days). Owners and admins.\n\nRequires the `billing:read` scope.",
        "tags": [
          "Credits"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "billing:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "grant",
                "debit",
                "adjust",
                "refund"
              ]
            }
          },
          {
            "name": "action",
            "in": "query",
            "required": false,
            "description": "Only this action (email.send, call.minute …).",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9_.]{1,64}$"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day (YYYY-MM-DD, UTC; default 29 days before `to`).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day (YYYY-MM-DD, UTC; default today).",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List the credit ledger",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "credit_ledger_entry"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "grant",
                              "debit",
                              "adjust",
                              "refund"
                            ],
                            "description": "grant, debit (a charge), adjust or refund."
                          },
                          "action": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "What was charged (email.send, call.minute …)."
                          },
                          "label": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "amount": {
                            "type": "object",
                            "properties": {
                              "credits": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991,
                                "description": "Whole credits (rounded half away from zero)."
                              },
                              "exact": {
                                "type": "string",
                                "pattern": "^-?\\d+(?:\\.\\d{1,2})?$",
                                "description": "The exact amount as a decimal string — a per-minute charge can hold a fraction of a credit."
                              }
                            },
                            "required": [
                              "credits",
                              "exact"
                            ],
                            "additionalProperties": false,
                            "description": "Signed: charges are negative."
                          },
                          "units": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "How many units were charged (minutes, segments, actions)."
                          },
                          "ref": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "object": {
                                    "type": "string"
                                  },
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                    "description": "An id (UUID)."
                                  }
                                },
                                "required": [
                                  "object",
                                  "id"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "What the charge was for, when it points at something the API knows."
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "kind",
                          "action",
                          "label",
                          "amount",
                          "units",
                          "ref",
                          "created_at"
                        ],
                        "additionalProperties": false,
                        "description": "One line of the credit ledger."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "9c8b7a6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
                      "object": "credit_ledger_entry",
                      "kind": "debit",
                      "action": "call.minute",
                      "label": "AI call minutes",
                      "amount": {
                        "credits": -30,
                        "exact": "-30"
                      },
                      "units": 2.5,
                      "ref": {
                        "object": "call",
                        "id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e"
                      },
                      "created_at": "2026-11-04T10:12:00.000Z"
                    }
                  ],
                  "has_more": true,
                  "next_cursor": "eyJ2IjoiMjAyNi0xMS0wNFQxMDoxMjowMC4wMDBaIiwiaSI6IjljOGI3YTZkIn0"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "billing:read",
        "x-norreach-action": "billing.view",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/credits/prices": {
      "get": {
        "operationId": "list_credit_prices",
        "summary": "List what actions cost",
        "description": "What each billable action costs in credits, per action, minute or segment — the workspace's own rate where one is set, the default otherwise. `confirmed: false` marks a default rate that isn't confirmed for billing yet. Rates are set by NorReach, not through the API. Owners and admins.\n\nRequires the `billing:read` scope.",
        "tags": [
          "Credits"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "billing:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List what actions cost",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "const": "credit_price"
                          },
                          "action": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "price": {
                            "type": "object",
                            "properties": {
                              "credits": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991,
                                "description": "Whole credits (rounded half away from zero)."
                              },
                              "exact": {
                                "type": "string",
                                "pattern": "^-?\\d+(?:\\.\\d{1,2})?$",
                                "description": "The exact amount as a decimal string — a per-minute charge can hold a fraction of a credit."
                              }
                            },
                            "required": [
                              "credits",
                              "exact"
                            ],
                            "additionalProperties": false,
                            "description": "Credits per unit."
                          },
                          "unit": {
                            "type": "string",
                            "enum": [
                              "per_action",
                              "per_minute",
                              "per_segment"
                            ]
                          },
                          "confirmed": {
                            "type": "boolean",
                            "description": "false = a default rate, not confirmed for billing yet."
                          },
                          "workspace_rate": {
                            "type": "boolean",
                            "description": "true = a rate set for this workspace (instead of the default)."
                          }
                        },
                        "required": [
                          "object",
                          "action",
                          "label",
                          "price",
                          "unit",
                          "confirmed",
                          "workspace_rate"
                        ],
                        "additionalProperties": false,
                        "description": "What an action costs."
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "const": false
                    },
                    "next_cursor": {
                      "type": "null"
                    },
                    "any_unconfirmed": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor",
                    "any_unconfirmed"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "credit_price",
                      "action": "email.send",
                      "label": "Emails sent",
                      "price": {
                        "credits": 1,
                        "exact": "1"
                      },
                      "unit": "per_action",
                      "confirmed": true,
                      "workspace_rate": false
                    },
                    {
                      "object": "credit_price",
                      "action": "call.minute",
                      "label": "AI call minutes",
                      "price": {
                        "credits": 12,
                        "exact": "12"
                      },
                      "unit": "per_minute",
                      "confirmed": true,
                      "workspace_rate": false
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null,
                  "any_unconfirmed": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "billing:read",
        "x-norreach-action": "billing.view",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/deals": {
      "get": {
        "operationId": "list_deals",
        "summary": "List deals",
        "description": "The pipeline's deals, newest first, with stage and value (minor units, EUR). Filter by `stage` or `contact_id`. Like the Pipeline page, for owners, admins and managers.\n\nRequires the `contacts:read` scope.",
        "tags": [
          "Deals"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "stage",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "contacted",
                "meeting",
                "qualified",
                "won",
                "lost"
              ]
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List deals",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "deal"
                          },
                          "contact_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "stage": {
                            "type": "string",
                            "description": "new, contacted, meeting, qualified, won or lost."
                          },
                          "value": {
                            "type": "object",
                            "properties": {
                              "amount_minor": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "currency": {
                                "type": "string",
                                "const": "EUR"
                              }
                            },
                            "required": [
                              "amount_minor",
                              "currency"
                            ],
                            "additionalProperties": false
                          },
                          "source": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "contact_id",
                          "stage",
                          "value",
                          "source",
                          "created_at"
                        ],
                        "additionalProperties": false,
                        "description": "A deal on the pipeline board."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "6c7d8e9f-0a1b-4c2d-9e3f-4a5b6c7d8e9f",
                      "object": "deal",
                      "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                      "stage": "meeting",
                      "value": {
                        "amount_minor": 1250000,
                        "currency": "EUR"
                      },
                      "source": "meeting",
                      "created_at": "2026-11-05T10:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/deals/{id}/move": {
      "post": {
        "operationId": "move_deal",
        "summary": "Move a deal",
        "description": "Moves a deal to another stage, exactly like dragging it on the board: recorded in the person's timeline. If someone else moved it in the meantime the answer is 409 conflict with the `stage` it is in now — nothing changes.\n\nRequires the `deals:write` scope.",
        "tags": [
          "Deals"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "deals:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "stage": {
                    "type": "string",
                    "enum": [
                      "new",
                      "contacted",
                      "meeting",
                      "qualified",
                      "won",
                      "lost"
                    ]
                  }
                },
                "required": [
                  "stage"
                ],
                "additionalProperties": false
              },
              "example": {
                "stage": "qualified"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Move a deal",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "deal_move"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "from": {
                      "type": "string"
                    },
                    "stage": {
                      "type": "string"
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "from",
                    "stage",
                    "changed",
                    "dry_run"
                  ],
                  "additionalProperties": false,
                  "description": "A deal moved to another stage."
                },
                "example": {
                  "object": "deal_move",
                  "id": "6c7d8e9f-0a1b-4c2d-9e3f-4a5b6c7d8e9f",
                  "from": "meeting",
                  "stage": "qualified",
                  "changed": true,
                  "dry_run": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "deals:write",
        "x-norreach-action": "deals.move",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/enrollments/{id}": {
      "get": {
        "operationId": "get_enrollment",
        "summary": "One enrollment",
        "description": "One contact's place in a campaign or automation: state, step and why it is paused.\n\nRequires the `campaigns:read` scope.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One enrollment",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "enrollment"
                    },
                    "campaign_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "contact_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "contact": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "email": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "name",
                            "email"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "state": {
                      "type": "string",
                      "description": "pending, active, paused, completed, replied, suppressed, meeting_booked …"
                    },
                    "current_step": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "The step (0-based) the contact is on."
                    },
                    "pause_reason": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Why it is paused (e.g. awaiting_approval, campaign_not_active, no_consent)."
                    },
                    "next_run_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "campaign_id",
                    "contact_id",
                    "contact",
                    "state",
                    "current_step",
                    "pause_reason",
                    "next_run_at",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "8e9f0a1b-2c3d-4e4f-9a5b-6c7d8e9f0a1b",
                  "object": "enrollment",
                  "campaign_id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "contact": {
                    "name": "Anna Lindqvist",
                    "email": "anna@example.com"
                  },
                  "state": "paused",
                  "current_step": 1,
                  "pause_reason": "awaiting_approval",
                  "next_run_at": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T10:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_enrollment",
        "summary": "Pause, resume or remove one contact",
        "description": "`pause` holds one contact; `resume` lets them carry on (a contact parked on a send that didn't go out tries that step again); `exit` takes them out of the campaign (as the leads list's Remove — they may be enrolled again later). A resume never side-steps another door: a send waiting for approval is decided in Approvals, a contact held because the campaign isn't running carries on when it is resumed, one without a lawful basis needs consent first (409 each), and nothing resumes while outreach is paused.\n\nRequires the `campaigns:launch` scope (reaches people, spends or publishes).",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:launch"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "pause",
                      "resume",
                      "exit"
                    ]
                  }
                },
                "required": [
                  "action"
                ],
                "additionalProperties": false
              },
              "example": {
                "action": "resume"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Pause, resume or remove one contact",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "enrollment_change"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "pause",
                        "resume",
                        "exit"
                      ]
                    },
                    "from": {
                      "type": "string"
                    },
                    "state": {
                      "type": "string",
                      "description": "The state now (removed after an exit)."
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "action",
                    "from",
                    "state",
                    "changed",
                    "dry_run",
                    "note"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "enrollment_change",
                  "id": "8e9f0a1b-2c3d-4e4f-9a5b-6c7d8e9f0a1b",
                  "action": "resume",
                  "from": "paused",
                  "state": "active",
                  "changed": true,
                  "dry_run": false,
                  "note": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:launch",
        "x-norreach-action": "campaigns.launch",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/event-types": {
      "get": {
        "operationId": "list_event_types",
        "summary": "The event catalogue",
        "description": "Every event a webhook endpoint can subscribe to, with the scope needed to receive it.\n\nAny valid key.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": []
          }
        ],
        "responses": {
          "200": {
            "description": "The event catalogue",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "const": "event_type"
                          },
                          "type": {
                            "type": "string"
                          },
                          "scope": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "resource": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "type",
                          "scope",
                          "resource",
                          "description"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "const": false
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "event_type",
                      "type": "lead.submitted",
                      "scope": "pages:read",
                      "resource": "lead",
                      "description": "Someone filled in a form on a landing page."
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "any",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/events": {
      "get": {
        "operationId": "list_events",
        "summary": "Poll events",
        "description": "The same events webhooks deliver, oldest first from `created_after` (default: the last 24 hours) — keep the `next_cursor` and poll again. Only the types this key's scopes may read are returned; filter further with `types[]`. Events are kept as long as the workspace's activity history.\n\nRequires the `workspace:read` scope.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "workspace:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "types",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "enum": [
                    "contact.created",
                    "contact.tag_added",
                    "contact.tag_removed",
                    "list.member_added",
                    "list.member_removed",
                    "consent.updated",
                    "contact.unsubscribed",
                    "deal.stage_changed",
                    "lead.submitted",
                    "ad_lead.received",
                    "message.received",
                    "message.sent",
                    "message.delivered",
                    "message.opened",
                    "message.clicked",
                    "message.bounced",
                    "message.blocked",
                    "message.failed",
                    "call.started",
                    "call.completed",
                    "meeting.booked",
                    "meeting.rescheduled",
                    "meeting.cancelled",
                    "meeting.requested",
                    "enrollment.created",
                    "enrollment.completed",
                    "enrollment.replied",
                    "enrollment.exited",
                    "enrollment.paused",
                    "approval.requested",
                    "page.published",
                    "page.unpublished",
                    "plan.generated",
                    "post.published",
                    "post.failed",
                    "number.purchased",
                    "ad_campaign.paused",
                    "ad_campaign.resumed",
                    "template.status_changed",
                    "ping"
                  ]
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "contact.created",
                      "contact.tag_added",
                      "contact.tag_removed",
                      "list.member_added",
                      "list.member_removed",
                      "consent.updated",
                      "contact.unsubscribed",
                      "deal.stage_changed",
                      "lead.submitted",
                      "ad_lead.received",
                      "message.received",
                      "message.sent",
                      "message.delivered",
                      "message.opened",
                      "message.clicked",
                      "message.bounced",
                      "message.blocked",
                      "message.failed",
                      "call.started",
                      "call.completed",
                      "meeting.booked",
                      "meeting.rescheduled",
                      "meeting.cancelled",
                      "meeting.requested",
                      "enrollment.created",
                      "enrollment.completed",
                      "enrollment.replied",
                      "enrollment.exited",
                      "enrollment.paused",
                      "approval.requested",
                      "page.published",
                      "page.unpublished",
                      "plan.generated",
                      "post.published",
                      "post.failed",
                      "number.purchased",
                      "ad_campaign.paused",
                      "ad_campaign.resumed",
                      "template.status_changed",
                      "ping"
                    ]
                  }
                }
              ]
            }
          },
          {
            "name": "created_after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Poll events",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "object": {
                            "type": "string",
                            "const": "event"
                          },
                          "type": {
                            "type": "string"
                          },
                          "api_version": {
                            "type": "string",
                            "const": "v1"
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "workspace_id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "data": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {}
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "type",
                          "api_version",
                          "created_at",
                          "workspace_id",
                          "data"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "evt_48213",
                      "object": "event",
                      "type": "lead.submitted",
                      "api_version": "v1",
                      "created_at": "2026-11-04T09:12:33.120Z",
                      "workspace_id": "5c3e2a10-9b8d-4f6e-a1c2-3d4e5f6a7b8c",
                      "data": {
                        "object": {
                          "id": "6b7c8d9e-0f1a-4b2c-9d3e-4f5a6b7c8d9e",
                          "object": "lead",
                          "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                          "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                          "network": "meta"
                        }
                      }
                    }
                  ],
                  "has_more": false,
                  "next_cursor": "eyJ2Ijo0ODIxMywiaSI6IiIsImYiOiJ…"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "workspace:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/inbound-routing": {
      "get": {
        "operationId": "get_inbound_routing",
        "summary": "Who answers incoming calls",
        "description": "The workspace's routing rules (per number, or for every number without its own: an AI agent, your team, the call menu or voicemail; by priority, optionally in business hours only) and the numbers whose answering can be switched between the AI agent and the call menu.\n\nRequires the `calls:read` scope.",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "calls:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Who answers incoming calls",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "inbound_routing"
                    },
                    "rules": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "routing_rule"
                          },
                          "phone_number_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Null = every number of the workspace without a rule of its own."
                          },
                          "route_type": {
                            "type": "string",
                            "enum": [
                              "ai_agent",
                              "human",
                              "ivr",
                              "voicemail"
                            ],
                            "description": "`ai_agent` = an AI agent answers; `human` = your team (the hold queue, or one person); `ivr` = the call menu; `voicemail`."
                          },
                          "ai_agent_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "assigned_user_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "priority": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "business_hours_only": {
                            "type": "boolean"
                          },
                          "greeting": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "active": {
                            "type": "boolean"
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "phone_number_id",
                          "route_type",
                          "ai_agent_id",
                          "assigned_user_id",
                          "priority",
                          "business_hours_only",
                          "greeting",
                          "active",
                          "created_at"
                        ],
                        "additionalProperties": false,
                        "description": "Who answers incoming calls, and when."
                      }
                    },
                    "numbers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "routing_number"
                          },
                          "number": {
                            "type": "string"
                          },
                          "label": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "inbound_mode": {
                            "type": "string",
                            "enum": [
                              "ai",
                              "menu"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "number",
                          "label",
                          "inbound_mode"
                        ],
                        "additionalProperties": false
                      },
                      "description": "The numbers whose answering can be switched (PUT /phone-numbers/{id}/inbound-mode)."
                    }
                  },
                  "required": [
                    "object",
                    "rules",
                    "numbers"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "inbound_routing",
                  "rules": [
                    {
                      "id": "0d1e2f3a-4b5c-4d6e-8f7a-8b9c0d1e2f3a",
                      "object": "routing_rule",
                      "phone_number_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                      "route_type": "ai_agent",
                      "ai_agent_id": "9c0d1e2f-3a4b-4c5d-8e6f-7a8b9c0d1e2f",
                      "assigned_user_id": null,
                      "priority": 10,
                      "business_hours_only": false,
                      "greeting": null,
                      "active": true,
                      "created_at": "2026-10-01T08:00:00.000Z"
                    }
                  ],
                  "numbers": [
                    {
                      "id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                      "object": "routing_number",
                      "number": "+46812345678",
                      "label": "Stockholm office",
                      "inbound_mode": "ai"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "calls:read",
        "x-norreach-action": null,
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/inbound-routing/rules": {
      "post": {
        "operationId": "create_routing_rule",
        "summary": "Add a routing rule",
        "description": "Adds who answers incoming calls: `ai_agent` (needs `ai_agent_id`), `human` (your team, or one person with `assigned_user_id`), `ivr` (the call menu) or `voicemail` — for one number (`phone_number_id`) or every number without a rule of its own; `priority` (higher first), `business_hours_only`, a `greeting` (≤ 1000 characters). Fields that don't belong to the type are left out. Owners, admins and managers. `dry_run=true` answers it as it would be saved.\n\nRequires the `calls:routing` scope (reaches people, spends or publishes).",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "calls:routing"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "route_type": {
                    "type": "string",
                    "enum": [
                      "ai_agent",
                      "human",
                      "ivr",
                      "voicemail"
                    ]
                  },
                  "phone_number_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "ai_agent_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "assigned_user_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "priority": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000
                  },
                  "business_hours_only": {
                    "type": "boolean"
                  },
                  "greeting": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 1000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "active": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "route_type"
                ],
                "additionalProperties": false
              },
              "example": {
                "route_type": "ai_agent",
                "phone_number_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                "ai_agent_id": "9c0d1e2f-3a4b-4c5d-8e6f-7a8b9c0d1e2f",
                "priority": 10
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Add a routing rule",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "routing_rule"
                    },
                    "phone_number_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Null = every number of the workspace without a rule of its own."
                    },
                    "route_type": {
                      "type": "string",
                      "enum": [
                        "ai_agent",
                        "human",
                        "ivr",
                        "voicemail"
                      ],
                      "description": "`ai_agent` = an AI agent answers; `human` = your team (the hold queue, or one person); `ivr` = the call menu; `voicemail`."
                    },
                    "ai_agent_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "assigned_user_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "priority": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "business_hours_only": {
                      "type": "boolean"
                    },
                    "greeting": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "active": {
                      "type": "boolean"
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "phone_number_id",
                    "route_type",
                    "ai_agent_id",
                    "assigned_user_id",
                    "priority",
                    "business_hours_only",
                    "greeting",
                    "active",
                    "created_at"
                  ],
                  "additionalProperties": false,
                  "description": "Who answers incoming calls, and when."
                },
                "example": {
                  "id": "0d1e2f3a-4b5c-4d6e-8f7a-8b9c0d1e2f3a",
                  "object": "routing_rule",
                  "phone_number_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "route_type": "ai_agent",
                  "ai_agent_id": "9c0d1e2f-3a4b-4c5d-8e6f-7a8b9c0d1e2f",
                  "assigned_user_id": null,
                  "priority": 10,
                  "business_hours_only": false,
                  "greeting": null,
                  "active": true,
                  "created_at": "2026-10-01T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "calls:routing",
        "x-norreach-action": "calls.routing",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/inbound-routing/rules/{id}": {
      "delete": {
        "operationId": "delete_routing_rule",
        "summary": "Remove a routing rule",
        "description": "Removes a rule. Calls it handled fall to the next rule (or the AI agent / voicemail fallback). Owners, admins and managers. `dry_run=true` changes nothing.\n\nRequires the `calls:routing` scope (reaches people, spends or publishes).",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "calls:routing"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Remove a routing rule",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "routing_rule_deletion"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "deleted": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "deleted",
                    "dry_run"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "routing_rule_deletion",
                  "id": "0d1e2f3a-4b5c-4d6e-8f7a-8b9c0d1e2f3a",
                  "deleted": true,
                  "dry_run": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "calls:routing",
        "x-norreach-action": "calls.routing",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_routing_rule",
        "summary": "Change a routing rule",
        "description": "Changes a rule — switch it on or off (`active`), its priority, hours, greeting, or who answers (the fields that no longer belong to its type are cleared). Owners, admins and managers. `dry_run=true` answers it as it would be.\n\nRequires the `calls:routing` scope (reaches people, spends or publishes).",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "calls:routing"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "route_type": {
                    "type": "string",
                    "enum": [
                      "ai_agent",
                      "human",
                      "ivr",
                      "voicemail"
                    ]
                  },
                  "phone_number_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "ai_agent_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "assigned_user_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "priority": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000
                  },
                  "business_hours_only": {
                    "type": "boolean"
                  },
                  "greeting": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 1000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "active": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "active": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Change a routing rule",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "routing_rule"
                    },
                    "phone_number_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Null = every number of the workspace without a rule of its own."
                    },
                    "route_type": {
                      "type": "string",
                      "enum": [
                        "ai_agent",
                        "human",
                        "ivr",
                        "voicemail"
                      ],
                      "description": "`ai_agent` = an AI agent answers; `human` = your team (the hold queue, or one person); `ivr` = the call menu; `voicemail`."
                    },
                    "ai_agent_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "assigned_user_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "priority": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "business_hours_only": {
                      "type": "boolean"
                    },
                    "greeting": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "active": {
                      "type": "boolean"
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "phone_number_id",
                    "route_type",
                    "ai_agent_id",
                    "assigned_user_id",
                    "priority",
                    "business_hours_only",
                    "greeting",
                    "active",
                    "created_at"
                  ],
                  "additionalProperties": false,
                  "description": "Who answers incoming calls, and when."
                },
                "example": {
                  "id": "0d1e2f3a-4b5c-4d6e-8f7a-8b9c0d1e2f3a",
                  "object": "routing_rule",
                  "phone_number_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "route_type": "ai_agent",
                  "ai_agent_id": "9c0d1e2f-3a4b-4c5d-8e6f-7a8b9c0d1e2f",
                  "assigned_user_id": null,
                  "priority": 10,
                  "business_hours_only": false,
                  "greeting": null,
                  "active": false,
                  "created_at": "2026-10-01T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "calls:routing",
        "x-norreach-action": "calls.routing",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/invites": {
      "get": {
        "operationId": "list_invites",
        "summary": "List pending invites",
        "description": "People invited to the workspace who haven't signed in yet: email, name, the role they were invited as, when, and who invited them. The invite link itself is never served — it's only in their email. The workspace's owner is never listed. One page.\n\nRequires the `team:read` scope.",
        "tags": [
          "Team"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "team:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List pending invites",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "The invited person's member id."
                          },
                          "object": {
                            "type": "string",
                            "const": "invite"
                          },
                          "email": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "name": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "caller",
                              "manager",
                              "admin"
                            ],
                            "description": "The role to give: `caller`, `manager` or `admin` (never `owner`)."
                          },
                          "active": {
                            "type": "boolean"
                          },
                          "invited_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "invited_by": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                    "description": "An id (UUID)."
                                  },
                                  "name": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  }
                                },
                                "required": [
                                  "id",
                                  "name"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Who invited them, when that person is still in the workspace."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "email",
                          "name",
                          "role",
                          "active",
                          "invited_at",
                          "invited_by"
                        ],
                        "additionalProperties": false,
                        "description": "A pending invite: someone invited who hasn't signed in yet."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "7c6b5a49-3827-4615-8a4b-3c2d1e0f9a8b",
                      "object": "invite",
                      "email": "sam@acme.example",
                      "name": "Sam Berg",
                      "role": "caller",
                      "active": true,
                      "invited_at": "2026-11-04T15:02:11.000Z",
                      "invited_by": {
                        "id": "3b2a1c0d-9e8f-4a7b-8c6d-5e4f3a2b1c0d",
                        "name": "Alex Andersson"
                      }
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "team:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "create_invite",
        "summary": "Invite someone",
        "description": "Emails an invitation to join the workspace as `role` (default caller; never owner, never above the key creator's own role). Owners, admins and managers; inviting a manager or an admin is a role decision, so it also needs an owner or admin AND the team:admin scope. Someone already in the workspace only gets the email again (their role is unchanged); an email that belongs to another workspace → 409 conflict. It emails a person, so an Idempotency-Key is required and `dry_run=true` previews it. At most 20 invitations an hour per workspace (and 5 a minute per key) → 429. The outreach pause doesn't apply (it isn't outreach).\n\nRequires the `team:write` scope.",
        "tags": [
          "Team"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "team:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "maxLength": 254,
                    "format": "email",
                    "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
                    "description": "Who to invite."
                  },
                  "name": {
                    "description": "Their name, for the email and the member list.",
                    "type": "string",
                    "maxLength": 120
                  },
                  "role": {
                    "default": "caller",
                    "type": "string",
                    "enum": [
                      "caller",
                      "manager",
                      "admin"
                    ],
                    "description": "The role to give: `caller`, `manager` or `admin` (never `owner`)."
                  }
                },
                "required": [
                  "email"
                ],
                "additionalProperties": false
              },
              "example": {
                "email": "sam@acme.example",
                "name": "Sam Berg",
                "role": "caller"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Invite someone",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The invited person's member id (null on a dry run for someone new)."
                    },
                    "object": {
                      "type": "string",
                      "const": "invite"
                    },
                    "email": {
                      "type": "string"
                    },
                    "name": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "owner",
                        "admin",
                        "manager",
                        "caller"
                      ],
                      "description": "The role they have — for someone already in the workspace, their own (an invite never changes it)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "sent",
                        "resent",
                        "dry_run"
                      ],
                      "description": "`resent` = they were already in the workspace: only the email went out again."
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "email",
                    "name",
                    "role",
                    "status",
                    "dry_run",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "An invitation email sent (or what would be sent)."
                },
                "example": {
                  "id": "7c6b5a49-3827-4615-8a4b-3c2d1e0f9a8b",
                  "object": "invite",
                  "email": "sam@acme.example",
                  "name": "Sam Berg",
                  "role": "caller",
                  "status": "sent",
                  "dry_run": false,
                  "note": "Invitation sent. They join with this role when they accept it."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "team:write",
        "x-norreach-action": "team.invite",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/invites/{id}": {
      "delete": {
        "operationId": "cancel_invite",
        "summary": "Cancel an invite",
        "description": "Cancels a pending invite (the id from GET /invites): the invitation stops working and the account it created, never used, is removed. Someone who has already signed in can't be un-invited → 409 conflict (switch them off with PATCH /members/{id} instead). Managers cancel callers' invites; anyone else's needs an owner or admin AND the team:admin scope. `dry_run=true` previews it.\n\nRequires the `team:write` scope.",
        "tags": [
          "Team"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "team:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cancel an invite",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "invite"
                    },
                    "canceled": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "canceled",
                    "dry_run",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "A cancelled invite: the unused account is removed."
                },
                "example": {
                  "id": "7c6b5a49-3827-4615-8a4b-3c2d1e0f9a8b",
                  "object": "invite",
                  "canceled": true,
                  "dry_run": false,
                  "note": "Invite cancelled. Their unused account is removed."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `member_locked` — This person's role or access can't be changed this way. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "team:write",
        "x-norreach-action": "team.invite",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/jobs/{id}": {
      "get": {
        "operationId": "get_job",
        "summary": "One async job",
        "description": "The status of a job an earlier request started — plan generation from POST /briefs, a re-plan from POST /plans/{id}/replan. Poll until `status` is `succeeded` (its `result` holds the answer, e.g. the plan id) or `failed` (its `error` is a problem). `resource` names what the job works on. Webhook subscribers get `plan.generated` when Nora finishes writing a plan.\n\nAny valid key.",
        "tags": [
          "Workspace"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One async job",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "job"
                    },
                    "type": {
                      "type": "string",
                      "description": "What the job does (e.g. contacts.import)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "running",
                        "succeeded",
                        "failed"
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "finished_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "result": {
                      "anyOf": [
                        {},
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The job's answer once it succeeded."
                    },
                    "error": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "description": "A URL identifying the problem type."
                            },
                            "title": {
                              "type": "string",
                              "description": "A short, human summary (follows Accept-Language)."
                            },
                            "status": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "The HTTP status."
                            },
                            "code": {
                              "type": "string",
                              "enum": [
                                "bad_request",
                                "unknown_field",
                                "invalid_cursor",
                                "idempotency_key_required",
                                "unauthorized",
                                "key_revoked",
                                "key_expired",
                                "legacy_key",
                                "test_keys_not_available",
                                "key_owner_inactive",
                                "insufficient_scope",
                                "role_forbidden",
                                "ip_not_allowed",
                                "workspace_suspended",
                                "feature_not_enabled",
                                "key_suspended",
                                "member_locked",
                                "not_found",
                                "method_not_allowed",
                                "conflict",
                                "outreach_paused",
                                "already_decided",
                                "idempotency_in_progress",
                                "no_sender",
                                "insufficient_credits",
                                "too_large",
                                "validation_failed",
                                "send_blocked",
                                "publish_blocked",
                                "ad_publish_blocked",
                                "ad_switch_blocked",
                                "ad_network_unsupported",
                                "post_schedule_blocked",
                                "ads_by_plan",
                                "idempotency_mismatch",
                                "rate_limited",
                                "send_cap_reached",
                                "number_cap_reached",
                                "server_error",
                                "unavailable"
                              ],
                              "description": "Stable machine-readable code."
                            },
                            "detail": {
                              "description": "What happened, for a person (follows Accept-Language).",
                              "type": "string"
                            },
                            "instance": {
                              "description": "The request id.",
                              "type": "string"
                            },
                            "errors": {
                              "description": "Field-level problems (validation_failed, unknown_field).",
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "path": {
                                    "type": "string"
                                  },
                                  "code": {
                                    "type": "string"
                                  },
                                  "message": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "path",
                                  "code",
                                  "message"
                                ],
                                "additionalProperties": false
                              }
                            },
                            "docs": {
                              "type": "string",
                              "description": "Where this code is explained."
                            }
                          },
                          "required": [
                            "type",
                            "title",
                            "status",
                            "code",
                            "docs"
                          ],
                          "additionalProperties": {},
                          "description": "RFC 9457 problem details."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Why it failed."
                    },
                    "resource": {
                      "description": "What the job works on — GET it for the full object.",
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "object": {
                              "type": "string",
                              "description": "What kind of thing (e.g. plan)."
                            },
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            }
                          },
                          "required": [
                            "object",
                            "id"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "type",
                    "status",
                    "created_at",
                    "finished_at",
                    "result",
                    "error"
                  ],
                  "additionalProperties": false,
                  "description": "A long-running job."
                },
                "example": {
                  "id": "2f9c1a7e-5b3d-4e8f-9a1b-6c7d8e9f0a1b",
                  "object": "job",
                  "type": "plan.generate",
                  "status": "succeeded",
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "finished_at": "2026-11-04T09:16:41.004Z",
                  "result": {
                    "plan_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                    "plan_status": "review"
                  },
                  "error": null,
                  "resource": {
                    "object": "plan",
                    "id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "any",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/leads": {
      "get": {
        "operationId": "list_leads",
        "summary": "List form leads",
        "description": "Form submissions from every landing page, newest first: the person's answers, the page, where they came from and their marketing opt-in. Spam is left out unless `spam=true`.\n\nRequires the `pages:read` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "default": "30",
              "type": "string",
              "enum": [
                "7",
                "30",
                "90",
                "all"
              ]
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "spam",
            "in": "query",
            "required": false,
            "schema": {
              "default": "false",
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List form leads",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "lead"
                          },
                          "page_id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "contact_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "network": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The ad network the visitor came from, if any."
                          },
                          "ad_key": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "campaign": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "marketing_opt_in": {
                            "type": "string",
                            "enum": [
                              "yes",
                              "no",
                              "not_asked"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "email": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "phone": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "answers": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "key": {
                                  "type": "string"
                                },
                                "label": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "value": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "boolean"
                                    }
                                  ]
                                }
                              },
                              "required": [
                                "key",
                                "label",
                                "value"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "page_title": {
                            "type": "string"
                          },
                          "page_url": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "page_id",
                          "contact_id",
                          "status",
                          "created_at",
                          "network",
                          "ad_key",
                          "campaign",
                          "marketing_opt_in",
                          "name",
                          "email",
                          "phone",
                          "answers",
                          "page_title",
                          "page_url"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "6b7c8d9e-0f1a-4b2c-9d3e-4f5a6b7c8d9e",
                      "object": "lead",
                      "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                      "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                      "status": "new",
                      "created_at": "2026-11-04T09:12:33.120Z",
                      "network": "meta",
                      "ad_key": null,
                      "campaign": "november",
                      "marketing_opt_in": "yes",
                      "name": "Maja Lind",
                      "email": "maja.lind@example.com",
                      "phone": null,
                      "answers": [
                        {
                          "key": "role",
                          "label": "Role",
                          "value": "Nurse"
                        }
                      ],
                      "page_title": "Nurses when you need them",
                      "page_url": "https://acme.norreach.page/nurses-stockholm"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/leads/export": {
      "post": {
        "operationId": "export_leads",
        "summary": "Export form leads",
        "description": "Up to 5 000 leads (one page's, or every page's) as CSV in the answer's `csv` field — cells that a spreadsheet would read as a formula are made safe. Needs contacts:export, and the key's creator must be someone who may edit landing pages (owners, admins, managers).\n\nRequires the `contacts:export` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:export"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "page_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "description": "An id (UUID)."
                  },
                  "days": {
                    "default": "30",
                    "type": "string",
                    "enum": [
                      "7",
                      "30",
                      "90",
                      "all"
                    ]
                  },
                  "q": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "spam": {
                    "default": false,
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "days": "30"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Export form leads",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "export"
                    },
                    "format": {
                      "type": "string",
                      "const": "csv"
                    },
                    "rows": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "csv": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "format",
                    "rows",
                    "csv"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "export",
                  "format": "csv",
                  "rows": 1,
                  "csv": "﻿\"Received\",\"Page\"\r\n\"2026-11-04T09:12:33.120Z\",\"Nurses when you need them\"\r\n"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:export",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/lists": {
      "get": {
        "operationId": "list_lists",
        "summary": "List lists",
        "description": "The workspace's contact lists, newest first.\n\nRequires the `contacts:read` scope.",
        "tags": [
          "Lists"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List lists",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "list"
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "name",
                          "description",
                          "created_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "9b2f7e1d-3c4a-4b5d-8e6f-7a8b9c0d1e2f",
                      "object": "list",
                      "name": "Webinar November",
                      "description": null,
                      "created_at": "2026-11-04T09:12:33.120Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "create_list",
        "summary": "Create a list",
        "description": "A new, empty contact list.\n\nRequires the `contacts:write` scope.",
        "tags": [
          "Lists"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 500
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "Webinar November"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Create a list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "name": {
                      "type": "string"
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "description",
                    "created_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "9b2f7e1d-3c4a-4b5d-8e6f-7a8b9c0d1e2f",
                  "object": "list",
                  "name": "Webinar November",
                  "description": null,
                  "created_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:write",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/lists/{id}/members": {
      "delete": {
        "operationId": "remove_list_members",
        "summary": "Remove contacts from a list",
        "description": "Takes up to 1 000 contacts off a list (send their ids in the body). The contacts themselves stay.\n\nRequires the `contacts:write` scope.",
        "tags": [
          "Lists"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contact_ids": {
                    "minItems": 1,
                    "maxItems": 1000,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    }
                  }
                },
                "required": [
                  "contact_ids"
                ],
                "additionalProperties": false
              },
              "example": {
                "contact_ids": [
                  "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Remove contacts from a list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list_members_change"
                    },
                    "list_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "added": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "removed": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "not_found": {
                      "description": "Ids that aren't contacts of this workspace (nothing was done with them).",
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      }
                    }
                  },
                  "required": [
                    "object",
                    "list_id"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list_members_change",
                  "list_id": "9b2f7e1d-3c4a-4b5d-8e6f-7a8b9c0d1e2f",
                  "removed": 1
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:write",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "get": {
        "operationId": "list_list_members",
        "summary": "List a list's members",
        "description": "Who is on a list, most recently added first. Fetch a contact with `GET /contacts/{id}`, or filter `GET /contacts?list_id=` for the full records.\n\nRequires the `contacts:read` scope.",
        "tags": [
          "Lists"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List a list's members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "const": "list_member"
                          },
                          "list_id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "contact_id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "added_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "object",
                          "list_id",
                          "contact_id",
                          "added_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "list_member",
                      "list_id": "9b2f7e1d-3c4a-4b5d-8e6f-7a8b9c0d1e2f",
                      "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                      "added_at": "2026-11-04T09:12:33.120Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "add_list_members",
        "summary": "Add contacts to a list",
        "description": "Adds up to 1 000 contacts to a list. Contacts already on it stay; ids that aren't this workspace's contacts are returned in `not_found` and skipped. Automations that start on a list run as they do in the app.\n\nRequires the `contacts:write` scope.",
        "tags": [
          "Lists"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contact_ids": {
                    "minItems": 1,
                    "maxItems": 1000,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    }
                  }
                },
                "required": [
                  "contact_ids"
                ],
                "additionalProperties": false
              },
              "example": {
                "contact_ids": [
                  "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Add contacts to a list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list_members_change"
                    },
                    "list_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "added": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "removed": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "not_found": {
                      "description": "Ids that aren't contacts of this workspace (nothing was done with them).",
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      }
                    }
                  },
                  "required": [
                    "object",
                    "list_id"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list_members_change",
                  "list_id": "9b2f7e1d-3c4a-4b5d-8e6f-7a8b9c0d1e2f",
                  "added": 1,
                  "not_found": []
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:write",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/me": {
      "get": {
        "operationId": "get_me",
        "summary": "Who this key is",
        "description": "The key (prefix, label, scopes, expiry), the person it acts as and their role, the workspace, and which features are on. Use it to check a key works and what it may do.\n\nAny valid key.",
        "tags": [
          "Workspace"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": []
          }
        ],
        "responses": {
          "200": {
            "description": "Who this key is",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "me"
                    },
                    "key": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        "object": {
                          "type": "string",
                          "const": "api_key"
                        },
                        "kind": {
                          "type": "string",
                          "enum": [
                            "api_key",
                            "oauth"
                          ],
                          "description": "An API key, or a connected app's grant."
                        },
                        "prefix": {
                          "type": "string",
                          "description": "The first characters of the key (safe to show)."
                        },
                        "label": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "scopes": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "workspace:read",
                              "contacts:read",
                              "contacts:write",
                              "contacts:export",
                              "contacts:delete",
                              "suppressions:write",
                              "campaigns:read",
                              "campaigns:write",
                              "campaigns:launch",
                              "plans:read",
                              "plans:write",
                              "plans:approve",
                              "approvals:read",
                              "approvals:decide",
                              "inbox:read",
                              "messages:send",
                              "calls:read",
                              "calls:recordings",
                              "calls:place",
                              "meetings:read",
                              "meetings:write",
                              "deals:write",
                              "pages:read",
                              "pages:write",
                              "pages:publish",
                              "pages:domains",
                              "ads:read",
                              "ads:spend",
                              "social:read",
                              "social:publish",
                              "nora:ask",
                              "nora:run",
                              "nora:autonomy",
                              "analytics:read",
                              "billing:read",
                              "team:read",
                              "team:write",
                              "team:admin",
                              "workspace:admin",
                              "webhooks:read",
                              "webhooks:write",
                              "audit:read",
                              "numbers:read",
                              "numbers:verify",
                              "numbers:buy",
                              "templates:read",
                              "templates:write",
                              "voice:write",
                              "calls:routing",
                              "team:schedules",
                              "team:requests",
                              "workspace:settings",
                              "ads:limits"
                            ]
                          }
                        },
                        "expires_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "object",
                        "kind",
                        "prefix",
                        "label",
                        "scopes",
                        "expires_at"
                      ],
                      "additionalProperties": false
                    },
                    "user": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        "object": {
                          "type": "string",
                          "const": "user"
                        },
                        "name": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "role": {
                          "type": "string",
                          "enum": [
                            "owner",
                            "admin",
                            "manager",
                            "caller"
                          ],
                          "description": "The key acts as this person, with this role (read live)."
                        }
                      },
                      "required": [
                        "id",
                        "object",
                        "name",
                        "role"
                      ],
                      "additionalProperties": false,
                      "description": "The person the key acts as — the person who created it."
                    },
                    "workspace": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        "object": {
                          "type": "string",
                          "const": "workspace"
                        },
                        "name": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "object",
                        "name"
                      ],
                      "additionalProperties": false
                    },
                    "features": {
                      "type": "object",
                      "properties": {
                        "landing_pages": {
                          "type": "boolean",
                          "description": "Hosted landing pages are on for this workspace."
                        }
                      },
                      "required": [
                        "landing_pages"
                      ],
                      "additionalProperties": false,
                      "description": "Features that change which operations answer."
                    }
                  },
                  "required": [
                    "object",
                    "key",
                    "user",
                    "workspace",
                    "features"
                  ],
                  "additionalProperties": false,
                  "description": "The key, the person it acts as, and the workspace."
                },
                "example": {
                  "object": "me",
                  "key": {
                    "id": "7a1d7f4e-3c1b-4a43-9a64-0d3c1b2f9e10",
                    "object": "api_key",
                    "kind": "api_key",
                    "prefix": "nr_live_8fK2pQ1x",
                    "label": "CRM sync",
                    "scopes": [
                      "contacts:read",
                      "contacts:write"
                    ],
                    "expires_at": null
                  },
                  "user": {
                    "id": "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00",
                    "object": "user",
                    "name": "Alex Andersson",
                    "role": "admin"
                  },
                  "workspace": {
                    "id": "5c3e2a10-9b8d-4f6e-a1c2-3d4e5f6a7b8c",
                    "object": "workspace",
                    "name": "Acme Staffing"
                  },
                  "features": {
                    "landing_pages": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "any",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/meeting-types": {
      "get": {
        "operationId": "list_meeting_types",
        "summary": "List meeting types",
        "description": "The kinds of meeting your booking page offers (Intro call, Demo …): length, place, hosts, buffers and notice. Pass one's id to GET /availability and POST /meetings.\n\nRequires the `meetings:read` scope.",
        "tags": [
          "Meetings"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "meetings:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "active",
            "in": "query",
            "required": false,
            "description": "Only switched-on (true) or switched-off (false) types.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List meeting types",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "meeting_type"
                          },
                          "slug": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "duration_minutes": {
                            "type": "number"
                          },
                          "location_kind": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "location_value": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "host_mode": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "round_robin or choose."
                          },
                          "host_ids": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            }
                          },
                          "buffer_before_minutes": {
                            "type": "number"
                          },
                          "buffer_after_minutes": {
                            "type": "number"
                          },
                          "min_notice_minutes": {
                            "type": "number"
                          },
                          "window_days": {
                            "type": "number"
                          },
                          "max_per_day": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "requires_confirmation": {
                            "type": "boolean",
                            "description": "Bookings from the page wait for a person's yes."
                          },
                          "active": {
                            "type": "boolean"
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "slug",
                          "name",
                          "description",
                          "duration_minutes",
                          "location_kind",
                          "location_value",
                          "host_mode",
                          "host_ids",
                          "buffer_before_minutes",
                          "buffer_after_minutes",
                          "min_notice_minutes",
                          "window_days",
                          "max_per_day",
                          "requires_confirmation",
                          "active",
                          "created_at"
                        ],
                        "additionalProperties": false,
                        "description": "A kind of meeting people can book (Intro call, Demo …)."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                      "object": "meeting_type",
                      "slug": "intro",
                      "name": "Intro call",
                      "description": null,
                      "duration_minutes": 30,
                      "location_kind": "video",
                      "location_value": null,
                      "host_mode": "round_robin",
                      "host_ids": [
                        "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00"
                      ],
                      "buffer_before_minutes": 0,
                      "buffer_after_minutes": 10,
                      "min_notice_minutes": 240,
                      "window_days": 30,
                      "max_per_day": null,
                      "requires_confirmation": false,
                      "active": true,
                      "created_at": "2026-10-08T09:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "meetings:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/meetings": {
      "get": {
        "operationId": "list_meetings",
        "summary": "List meetings",
        "description": "The workspace's meetings in time order (earliest first). Filter by `status` (pending_approval = waiting for a person's yes), `host_id`, `contact_id`, and a start range `from` / `to`.\n\nRequires the `meetings:read` scope.",
        "tags": [
          "Meetings"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "meetings:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 40
            }
          },
          {
            "name": "host_id",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Meetings starting at or after this time.",
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Meetings starting at or before this time.",
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List meetings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "meeting"
                          },
                          "title": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "type": "string",
                            "description": "pending_approval (waits for a person's yes), scheduled, in_progress, completed, cancelled …"
                          },
                          "starts_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "ends_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "duration_minutes": {
                            "type": "number"
                          },
                          "host_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The member hosting it (who it's assigned to, else who it was booked for)."
                          },
                          "contact_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "meeting_type_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "source": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "How it was booked: booking_page, nora (Nora or the API), manual, ai_detected."
                          },
                          "attendee": {
                            "type": "object",
                            "properties": {
                              "name": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "email": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "timezone": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "company": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              }
                            },
                            "required": [
                              "name",
                              "email",
                              "timezone",
                              "company"
                            ],
                            "additionalProperties": false
                          },
                          "location_kind": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "video, phone, in_person or link (booking-page meetings)."
                          },
                          "join_url": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "campaign_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "updated_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "title",
                          "status",
                          "starts_at",
                          "ends_at",
                          "duration_minutes",
                          "host_id",
                          "contact_id",
                          "meeting_type_id",
                          "source",
                          "attendee",
                          "location_kind",
                          "join_url",
                          "campaign_id",
                          "created_at",
                          "updated_at"
                        ],
                        "additionalProperties": false,
                        "description": "A meeting on the workspace's calendar."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "4a5b6c7d-8e9f-4a0b-9c1d-2e3f4a5b6c7d",
                      "object": "meeting",
                      "title": "Intro call: Anna Lindqvist (Example Care AB)",
                      "status": "pending_approval",
                      "starts_at": "2026-11-12T09:00:00.000Z",
                      "ends_at": "2026-11-12T09:30:00.000Z",
                      "duration_minutes": 30,
                      "host_id": "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00",
                      "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                      "meeting_type_id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                      "source": "nora",
                      "attendee": {
                        "name": "Anna Lindqvist",
                        "email": "anna@example.com",
                        "timezone": "Europe/Stockholm",
                        "company": "Example Care AB"
                      },
                      "location_kind": "video",
                      "join_url": null,
                      "campaign_id": null,
                      "created_at": "2026-11-05T10:00:00.000Z",
                      "updated_at": "2026-11-05T10:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "meetings:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "book_meeting",
        "summary": "Book a meeting with a contact",
        "description": "Books a SAVED contact (with an email address) at one of the free times GET /availability lists, through your booking page: the time is checked again against the hosts' calendars and reserved in one step (two bookings can't take it), the host's calendar gets the event, the contact gets the invitation and their running sequences end. It waits for a person's yes when the workspace's assisted bookings do (see GET /booking-pages). Without `meeting_type_id` the page's default type; without `host_id` the type's own rule picks a free host. Members who aren't owners, admins or managers book only meetings they host. A time that isn't free (any more) → 409 conflict with `conflict.choices`.\n\nRequires the `meetings:write` scope.",
        "tags": [
          "Meetings"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "meetings:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contact_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "description": "An id (UUID)."
                  },
                  "start": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "description": "One of the `slots[].start` of GET /availability."
                  },
                  "meeting_type_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "description": "An id (UUID)."
                  },
                  "host_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "description": "An id (UUID)."
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 1000
                  }
                },
                "required": [
                  "contact_id",
                  "start"
                ],
                "additionalProperties": false
              },
              "example": {
                "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                "start": "2026-11-12T09:00:00.000Z",
                "meeting_type_id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Book a meeting with a contact",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        "object": {
                          "type": "string",
                          "const": "meeting"
                        },
                        "title": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "status": {
                          "type": "string",
                          "description": "pending_approval (waits for a person's yes), scheduled, in_progress, completed, cancelled …"
                        },
                        "starts_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "ends_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "duration_minutes": {
                          "type": "number"
                        },
                        "host_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "The member hosting it (who it's assigned to, else who it was booked for)."
                        },
                        "contact_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "meeting_type_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "source": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "How it was booked: booking_page, nora (Nora or the API), manual, ai_detected."
                        },
                        "attendee": {
                          "type": "object",
                          "properties": {
                            "name": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "email": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "timezone": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "company": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "name",
                            "email",
                            "timezone",
                            "company"
                          ],
                          "additionalProperties": false
                        },
                        "location_kind": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "video, phone, in_person or link (booking-page meetings)."
                        },
                        "join_url": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "campaign_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "created_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "updated_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "object",
                        "title",
                        "status",
                        "starts_at",
                        "ends_at",
                        "duration_minutes",
                        "host_id",
                        "contact_id",
                        "meeting_type_id",
                        "source",
                        "attendee",
                        "location_kind",
                        "join_url",
                        "campaign_id",
                        "created_at",
                        "updated_at"
                      ],
                      "additionalProperties": false,
                      "description": "A meeting on the workspace's calendar."
                    },
                    {
                      "type": "object",
                      "properties": {
                        "object": {
                          "type": "string",
                          "const": "booking_preview"
                        },
                        "dry_run": {
                          "type": "boolean",
                          "const": true
                        },
                        "contact_id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        "meeting_type_id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        "starts_at": {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        "host_ids": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "description": "Who is free to take it then."
                        },
                        "status": {
                          "type": "string",
                          "description": "The status it would get: pending_approval when assisted bookings wait for a yes, else scheduled."
                        },
                        "note": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "object",
                        "dry_run",
                        "contact_id",
                        "meeting_type_id",
                        "starts_at",
                        "host_ids",
                        "status",
                        "note"
                      ],
                      "additionalProperties": false,
                      "description": "What booking would do (dry run)."
                    }
                  ]
                },
                "example": {
                  "id": "4a5b6c7d-8e9f-4a0b-9c1d-2e3f4a5b6c7d",
                  "object": "meeting",
                  "title": "Intro call: Anna Lindqvist (Example Care AB)",
                  "status": "pending_approval",
                  "starts_at": "2026-11-12T09:00:00.000Z",
                  "ends_at": "2026-11-12T09:30:00.000Z",
                  "duration_minutes": 30,
                  "host_id": "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00",
                  "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "meeting_type_id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                  "source": "nora",
                  "attendee": {
                    "name": "Anna Lindqvist",
                    "email": "anna@example.com",
                    "timezone": "Europe/Stockholm",
                    "company": "Example Care AB"
                  },
                  "location_kind": "video",
                  "join_url": null,
                  "campaign_id": null,
                  "created_at": "2026-11-05T10:00:00.000Z",
                  "updated_at": "2026-11-05T10:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "meetings:write",
        "x-norreach-action": "meetings.own",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/meetings/{id}": {
      "get": {
        "operationId": "get_meeting",
        "summary": "One meeting",
        "description": "A meeting: when, who hosts it, the attendee, how it was booked and its status.\n\nRequires the `meetings:read` scope.",
        "tags": [
          "Meetings"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "meetings:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One meeting",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "meeting"
                    },
                    "title": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string",
                      "description": "pending_approval (waits for a person's yes), scheduled, in_progress, completed, cancelled …"
                    },
                    "starts_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "ends_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "duration_minutes": {
                      "type": "number"
                    },
                    "host_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The member hosting it (who it's assigned to, else who it was booked for)."
                    },
                    "contact_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "meeting_type_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "source": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "How it was booked: booking_page, nora (Nora or the API), manual, ai_detected."
                    },
                    "attendee": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "email": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "timezone": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "company": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "email",
                        "timezone",
                        "company"
                      ],
                      "additionalProperties": false
                    },
                    "location_kind": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "video, phone, in_person or link (booking-page meetings)."
                    },
                    "join_url": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "campaign_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updated_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "title",
                    "status",
                    "starts_at",
                    "ends_at",
                    "duration_minutes",
                    "host_id",
                    "contact_id",
                    "meeting_type_id",
                    "source",
                    "attendee",
                    "location_kind",
                    "join_url",
                    "campaign_id",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "A meeting on the workspace's calendar."
                },
                "example": {
                  "id": "4a5b6c7d-8e9f-4a0b-9c1d-2e3f4a5b6c7d",
                  "object": "meeting",
                  "title": "Intro call: Anna Lindqvist (Example Care AB)",
                  "status": "pending_approval",
                  "starts_at": "2026-11-12T09:00:00.000Z",
                  "ends_at": "2026-11-12T09:30:00.000Z",
                  "duration_minutes": 30,
                  "host_id": "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00",
                  "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "meeting_type_id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                  "source": "nora",
                  "attendee": {
                    "name": "Anna Lindqvist",
                    "email": "anna@example.com",
                    "timezone": "Europe/Stockholm",
                    "company": "Example Care AB"
                  },
                  "location_kind": "video",
                  "join_url": null,
                  "campaign_id": null,
                  "created_at": "2026-11-05T10:00:00.000Z",
                  "updated_at": "2026-11-05T10:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "meetings:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/meetings/{id}/approve": {
      "post": {
        "operationId": "approve_meeting",
        "summary": "Approve a meeting",
        "description": "Confirms a meeting that waits for a yes (`pending_approval`): the host's calendar gets the event and the attendee the invitation. Optionally move it (`starts_at`, `duration_minutes`), fix the attendee's email, or give it to another host (`host_id` — owners, admins and managers only). Who may approve: the meeting's host, or an owner, admin or manager. A clash with the host's calendar, working hours or another meeting → 409 conflict with `conflict.reason` and `conflict.choices` (send `force: true` to approve anyway, pick another time, or decline).\n\nRequires the `meetings:write` scope.",
        "tags": [
          "Meetings"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "meetings:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "starts_at": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                  },
                  "duration_minutes": {
                    "type": "integer",
                    "minimum": 5,
                    "maximum": 480
                  },
                  "attendee_email": {
                    "type": "string",
                    "maxLength": 254,
                    "format": "email",
                    "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  },
                  "host_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "description": "An id (UUID)."
                  },
                  "force": {
                    "description": "Approve even though the time clashes.",
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "force": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Approve a meeting",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "meeting_decision"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "decision": {
                      "type": "string",
                      "enum": [
                        "approve",
                        "decline",
                        "reassign"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "description": "The meeting's status now (or, in a dry run, the one it would get)."
                    },
                    "host_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "invite_sent": {
                      "anyOf": [
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Approve: whether the attendee's invitation went out (no calendar connected for the host → false)."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "decision",
                    "status",
                    "host_id",
                    "changed",
                    "dry_run",
                    "invite_sent",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "What deciding a meeting did."
                },
                "example": {
                  "object": "meeting_decision",
                  "id": "4a5b6c7d-8e9f-4a0b-9c1d-2e3f4a5b6c7d",
                  "decision": "approve",
                  "status": "scheduled",
                  "host_id": "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00",
                  "changed": true,
                  "dry_run": false,
                  "invite_sent": true,
                  "note": "Confirmed — the invitation is on its way."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `already_decided` — Already handled. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "meetings:write",
        "x-norreach-action": "meetings.own",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/meetings/{id}/decline": {
      "post": {
        "operationId": "decline_meeting",
        "summary": "Decline or cancel a meeting",
        "description": "Declines a meeting that waits for a yes, or cancels a booked one: the calendar event goes, and an attendee who booked through your page hears (with a link to pick another time). Who may: the meeting's host, or an owner, admin or manager. Works while outreach is paused.\n\nRequires the `meetings:write` scope.",
        "tags": [
          "Meetings"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "meetings:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "reason": "The client cancelled the project."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Decline or cancel a meeting",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "meeting_decision"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "decision": {
                      "type": "string",
                      "enum": [
                        "approve",
                        "decline",
                        "reassign"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "description": "The meeting's status now (or, in a dry run, the one it would get)."
                    },
                    "host_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "invite_sent": {
                      "anyOf": [
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Approve: whether the attendee's invitation went out (no calendar connected for the host → false)."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "decision",
                    "status",
                    "host_id",
                    "changed",
                    "dry_run",
                    "invite_sent",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "What deciding a meeting did."
                },
                "example": {
                  "object": "meeting_decision",
                  "id": "4a5b6c7d-8e9f-4a0b-9c1d-2e3f4a5b6c7d",
                  "decision": "decline",
                  "status": "cancelled",
                  "host_id": "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00",
                  "changed": true,
                  "dry_run": false,
                  "invite_sent": null,
                  "note": "Declined — they've been told."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `already_decided` — Already handled. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "meetings:write",
        "x-norreach-action": "meetings.own",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/meetings/{id}/reassign": {
      "post": {
        "operationId": "reassign_meeting",
        "summary": "Hand a meeting to someone else",
        "description": "Gives a meeting (waiting or booked) to another member of the workspace: their Google Calendar gets the event when connected, and both are notified. Owners, admins and managers only — also for a meeting the key's creator hosts. A clash in the new host's calendar → 409 conflict (send `force: true` to hand it over anyway).\n\nRequires the `meetings:write` scope.",
        "tags": [
          "Meetings"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "meetings:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "host_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "description": "The member who takes it."
                  },
                  "reason": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "force": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "host_id"
                ],
                "additionalProperties": false
              },
              "example": {
                "host_id": "1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
                "reason": "Omar covers the north region."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Hand a meeting to someone else",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "meeting_decision"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "decision": {
                      "type": "string",
                      "enum": [
                        "approve",
                        "decline",
                        "reassign"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "description": "The meeting's status now (or, in a dry run, the one it would get)."
                    },
                    "host_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "invite_sent": {
                      "anyOf": [
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Approve: whether the attendee's invitation went out (no calendar connected for the host → false)."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "decision",
                    "status",
                    "host_id",
                    "changed",
                    "dry_run",
                    "invite_sent",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "What deciding a meeting did."
                },
                "example": {
                  "object": "meeting_decision",
                  "id": "4a5b6c7d-8e9f-4a0b-9c1d-2e3f4a5b6c7d",
                  "decision": "reassign",
                  "status": "scheduled",
                  "host_id": "1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
                  "changed": true,
                  "dry_run": false,
                  "invite_sent": null,
                  "note": "Handed over — they've been told."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `already_decided` — Already handled. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "meetings:write",
        "x-norreach-action": "meetings.decide",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/members": {
      "get": {
        "operationId": "list_members",
        "summary": "List members",
        "description": "Everyone in the workspace — name, email, role, whether they're switched on, whether they are the workspace's owner, and when they joined — in the order they joined. People invited who haven't signed in yet are members too (GET /invites lists them). One page (workspaces are small). Filter by `role` or `active`.\n\nRequires the `team:read` scope.",
        "tags": [
          "Team"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "team:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "role",
            "in": "query",
            "required": false,
            "description": "Only this role.",
            "schema": {
              "type": "string",
              "enum": [
                "owner",
                "admin",
                "manager",
                "caller"
              ]
            }
          },
          {
            "name": "active",
            "in": "query",
            "required": false,
            "description": "Only switched-on (true) or switched-off (false) people.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "member"
                          },
                          "name": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "email": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "owner",
                              "admin",
                              "manager",
                              "caller"
                            ],
                            "description": "owner > admin > manager > caller."
                          },
                          "active": {
                            "type": "boolean",
                            "description": "false = switched off: they (and API keys they created) can't use the workspace."
                          },
                          "is_owner": {
                            "type": "boolean",
                            "description": "The workspace's owner — never changed through the API."
                          },
                          "joined_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "When they were added (invited people: when the invite went out)."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "name",
                          "email",
                          "role",
                          "active",
                          "is_owner",
                          "joined_at"
                        ],
                        "additionalProperties": false,
                        "description": "A person in the workspace."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "0d1c2b3a-4f5e-4d6c-8b7a-9f8e7d6c5b4a",
                      "object": "member",
                      "name": "Kim Owner",
                      "email": "kim@acme.example",
                      "role": "owner",
                      "active": true,
                      "is_owner": true,
                      "joined_at": "2026-09-14T08:30:00.000Z"
                    },
                    {
                      "id": "3b2a1c0d-9e8f-4a7b-8c6d-5e4f3a2b1c0d",
                      "object": "member",
                      "name": "Alex Andersson",
                      "email": "alex@acme.example",
                      "role": "manager",
                      "active": true,
                      "is_owner": false,
                      "joined_at": "2026-09-14T08:30:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "team:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/members/{id}": {
      "patch": {
        "operationId": "update_member",
        "summary": "Change a member's role or switch them off",
        "description": "Sets `role` (caller, manager or admin — never owner) and/or `active` (false switches them off: they can't use the workspace, and API keys they created stop working at once; true switches them back on). Owners and admins, with the team:admin scope. Refused with 403 member_locked (`reason`): the key's creator's own row (`own_row`), the workspace's owner (`workspace_owner`), or someone above the creator's role / a role above it (`above_your_role`). Nothing is deleted.\n\nRequires the `team:admin` scope (reaches people, spends or publishes).",
        "tags": [
          "Team"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "team:admin"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "role": {
                    "type": "string",
                    "enum": [
                      "caller",
                      "manager",
                      "admin"
                    ],
                    "description": "The role to give: `caller`, `manager` or `admin` (never `owner`)."
                  },
                  "active": {
                    "description": "false switches them off, true back on.",
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "active": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Change a member's role or switch them off",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "member"
                    },
                    "name": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "email": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "owner",
                        "admin",
                        "manager",
                        "caller"
                      ],
                      "description": "owner > admin > manager > caller."
                    },
                    "active": {
                      "type": "boolean",
                      "description": "false = switched off: they (and API keys they created) can't use the workspace."
                    },
                    "is_owner": {
                      "type": "boolean",
                      "description": "The workspace's owner — never changed through the API."
                    },
                    "joined_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "When they were added (invited people: when the invite went out)."
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "email",
                    "role",
                    "active",
                    "is_owner",
                    "joined_at",
                    "changed",
                    "dry_run",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "The member after the change (a dry run: as it would be)."
                },
                "example": {
                  "id": "3b2a1c0d-9e8f-4a7b-8c6d-5e4f3a2b1c0d",
                  "object": "member",
                  "name": "Alex Andersson",
                  "email": "alex@acme.example",
                  "role": "manager",
                  "active": false,
                  "is_owner": false,
                  "joined_at": "2026-09-14T08:30:00.000Z",
                  "changed": true,
                  "dry_run": false,
                  "note": "Switched off: they can't use the workspace any more, and API keys they created stop working."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `member_locked` — This person's role or access can't be changed this way. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "team:admin",
        "x-norreach-action": "team.roles",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/members/{id}/schedule": {
      "get": {
        "operationId": "get_member_schedule",
        "summary": "A member's working hours",
        "description": "A member's working hours per weekday, their time zone and whether they're taking calls now. `source: default` = nothing saved yet (the app then assumes Monday–Friday 09:00–17:00 in the workspace's time zone).\n\nRequires the `team:read` scope.",
        "tags": [
          "Team"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "team:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A member's working hours",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "member_schedule"
                    },
                    "member_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "timezone": {
                      "type": "string"
                    },
                    "schedule_type": {
                      "type": "string",
                      "enum": [
                        "scheduled",
                        "flexible"
                      ]
                    },
                    "is_online": {
                      "type": "boolean",
                      "description": "Taking calls now (the team's hold queue and inbound routing read it)."
                    },
                    "hours": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "day_of_week": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 6,
                            "description": "0 = Sunday … 6 = Saturday."
                          },
                          "start": {
                            "type": "string",
                            "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                            "description": "HH:MM, 24-hour (24:00 = midnight at the end of the day)."
                          },
                          "end": {
                            "type": "string",
                            "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                            "description": "HH:MM, 24-hour (24:00 = midnight at the end of the day)."
                          },
                          "enabled": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "day_of_week",
                          "start",
                          "end",
                          "enabled"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "manual",
                        "calendar",
                        "default"
                      ],
                      "description": "`default` = none saved yet: Monday–Friday 09:00–17:00 in the workspace's time zone, as the app assumes."
                    }
                  },
                  "required": [
                    "object",
                    "member_id",
                    "timezone",
                    "schedule_type",
                    "is_online",
                    "hours",
                    "source"
                  ],
                  "additionalProperties": false,
                  "description": "A member's working hours and availability."
                },
                "example": {
                  "object": "member_schedule",
                  "member_id": "8e9f0a1b-2c3d-4e4f-9a5b-6c7d8e9f0a1b",
                  "timezone": "Europe/Stockholm",
                  "schedule_type": "scheduled",
                  "is_online": true,
                  "hours": [
                    {
                      "day_of_week": 1,
                      "start": "08:00",
                      "end": "16:30",
                      "enabled": true
                    },
                    {
                      "day_of_week": 2,
                      "start": "08:00",
                      "end": "16:30",
                      "enabled": true
                    },
                    {
                      "day_of_week": 3,
                      "start": "08:00",
                      "end": "16:30",
                      "enabled": true
                    },
                    {
                      "day_of_week": 4,
                      "start": "08:00",
                      "end": "16:30",
                      "enabled": true
                    },
                    {
                      "day_of_week": 5,
                      "start": "08:00",
                      "end": "16:30",
                      "enabled": true
                    }
                  ],
                  "source": "manual"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "team:read",
        "x-norreach-action": null,
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "put": {
        "operationId": "update_member_schedule",
        "summary": "Set a member's working hours",
        "description": "Sets a member's working hours (per weekday: start and end HH:MM, on or off — days left out stay as they are), their time zone, whether their schedule is fixed or flexible, and whether they're taking calls now. Checked on the server: each day once, end after start, a real time zone. Owners, admins and managers, for anyone in the workspace. `dry_run=true` answers it as it would be saved.\n\nRequires the `team:schedules` scope.",
        "tags": [
          "Team"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "team:schedules"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "timezone": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "schedule_type": {
                    "type": "string",
                    "enum": [
                      "scheduled",
                      "flexible"
                    ]
                  },
                  "is_online": {
                    "type": "boolean"
                  },
                  "hours": {
                    "description": "Days left out stay as they are.",
                    "maxItems": 7,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "day_of_week": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 6,
                          "description": "0 = Sunday … 6 = Saturday."
                        },
                        "start": {
                          "type": "string",
                          "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                          "description": "HH:MM, 24-hour (24:00 = midnight at the end of the day)."
                        },
                        "end": {
                          "type": "string",
                          "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                          "description": "HH:MM, 24-hour (24:00 = midnight at the end of the day)."
                        },
                        "enabled": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "day_of_week",
                        "start",
                        "end",
                        "enabled"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "timezone": "Europe/Stockholm",
                "hours": [
                  {
                    "day_of_week": 5,
                    "start": "08:00",
                    "end": "14:00",
                    "enabled": true
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Set a member's working hours",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "member_schedule"
                    },
                    "member_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "timezone": {
                      "type": "string"
                    },
                    "schedule_type": {
                      "type": "string",
                      "enum": [
                        "scheduled",
                        "flexible"
                      ]
                    },
                    "is_online": {
                      "type": "boolean",
                      "description": "Taking calls now (the team's hold queue and inbound routing read it)."
                    },
                    "hours": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "day_of_week": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 6,
                            "description": "0 = Sunday … 6 = Saturday."
                          },
                          "start": {
                            "type": "string",
                            "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                            "description": "HH:MM, 24-hour (24:00 = midnight at the end of the day)."
                          },
                          "end": {
                            "type": "string",
                            "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                            "description": "HH:MM, 24-hour (24:00 = midnight at the end of the day)."
                          },
                          "enabled": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "day_of_week",
                          "start",
                          "end",
                          "enabled"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "manual",
                        "calendar",
                        "default"
                      ],
                      "description": "`default` = none saved yet: Monday–Friday 09:00–17:00 in the workspace's time zone, as the app assumes."
                    }
                  },
                  "required": [
                    "object",
                    "member_id",
                    "timezone",
                    "schedule_type",
                    "is_online",
                    "hours",
                    "source"
                  ],
                  "additionalProperties": false,
                  "description": "A member's working hours and availability."
                },
                "example": {
                  "object": "member_schedule",
                  "member_id": "8e9f0a1b-2c3d-4e4f-9a5b-6c7d8e9f0a1b",
                  "timezone": "Europe/Stockholm",
                  "schedule_type": "scheduled",
                  "is_online": true,
                  "hours": [
                    {
                      "day_of_week": 1,
                      "start": "08:00",
                      "end": "16:30",
                      "enabled": true
                    },
                    {
                      "day_of_week": 2,
                      "start": "08:00",
                      "end": "16:30",
                      "enabled": true
                    },
                    {
                      "day_of_week": 3,
                      "start": "08:00",
                      "end": "16:30",
                      "enabled": true
                    },
                    {
                      "day_of_week": 4,
                      "start": "08:00",
                      "end": "16:30",
                      "enabled": true
                    },
                    {
                      "day_of_week": 5,
                      "start": "08:00",
                      "end": "16:30",
                      "enabled": true
                    }
                  ],
                  "source": "manual"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "team:schedules",
        "x-norreach-action": "team.schedules",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/messages": {
      "post": {
        "operationId": "send_message",
        "summary": "Send a message",
        "description": "Asks for a new email, SMS or WhatsApp message to a SAVED contact (never a free-typed address). It is an API send: it waits in Approvals when the workspace (or `campaign_id`'s campaign) approves before sending, or when the key lacks `approvals:decide`; `approve: true` (with `approvals:decide`) approves it in the same request. When it goes out the engine runs the full send gate again (suppression, do-not-contact, lawful basis, quiet hours, sending window). Up front: blocked → 422 send_blocked with `reason`; the API's hourly cap (500 messages per workspace) → 429 send_cap_reached. WhatsApp outside the 24-hour window needs an approved `template`. Poll the result with GET /messages/{id}.\n\nRequires the `messages:send` scope (reaches people, spends or publishes).",
        "tags": [
          "Inbox"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "messages:send"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contact_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "description": "An id (UUID)."
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "email",
                      "sms",
                      "whatsapp"
                    ]
                  },
                  "text": {
                    "description": "The message (required unless `template`).",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000
                  },
                  "subject": {
                    "description": "Email: the subject line (required for email).",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "template": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 512,
                        "description": "An approved WhatsApp template of this workspace (GET /templates)."
                      },
                      "language": {
                        "description": "Its language code, e.g. sv or en_US (default: the template's own).",
                        "type": "string",
                        "maxLength": 20
                      },
                      "params": {
                        "default": [],
                        "description": "Values for the template's variables, in order.",
                        "maxItems": 20,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "maxLength": 1024
                        }
                      }
                    },
                    "required": [
                      "name"
                    ],
                    "additionalProperties": false
                  },
                  "campaign_id": {
                    "description": "Send under this campaign's settings (approval mode, sending window).",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "approve": {
                    "default": false,
                    "type": "boolean"
                  }
                },
                "required": [
                  "contact_id",
                  "channel"
                ],
                "additionalProperties": false
              },
              "example": {
                "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                "channel": "email",
                "subject": "Nurses for the summer",
                "text": "Hi Maja, …"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Send a message",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "send_request"
                    },
                    "id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The request's id — poll GET /messages/{id} or GET /calls/{id} with it."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "message",
                        "call"
                      ]
                    },
                    "channel": {
                      "type": "string"
                    },
                    "contact_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "awaiting_approval",
                        "queued",
                        "dry_run"
                      ],
                      "description": "awaiting_approval = it waits in Approvals; queued = approved, it goes out within a minute through the send checks."
                    },
                    "approval_key": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The Approvals key (approve it with POST /approvals/{key}/approve)."
                    },
                    "note": {
                      "type": "string"
                    },
                    "would": {
                      "description": "Dry run: what would happen.",
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "awaiting_approval",
                            "queued"
                          ]
                        }
                      },
                      "required": [
                        "status"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "kind",
                    "channel",
                    "contact_id",
                    "status",
                    "approval_key",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "A send asked for through the API. It never skips the send checks or the approval queue."
                },
                "example": {
                  "object": "send_request",
                  "id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "kind": "message",
                  "channel": "email",
                  "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "status": "awaiting_approval",
                  "approval_key": "rule_send:5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "note": "It waits in Approvals until someone says yes."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request. · `send_blocked` — This can't be sent to this person.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again. · `send_cap_reached` — The workspace's sending limit for now is reached.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "messages:send",
        "x-norreach-action": "inbox.reply",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/messages/{id}": {
      "get": {
        "operationId": "get_message",
        "summary": "One message, or where an API send stands",
        "description": "With a message id: the message and its status (queued, sent, delivered, opened, bounced, failed with the reason). With the `id` POST /messages answered: where the send stands — awaiting_approval, skipped, queued, blocked (with `reason`), sent or failed — and the message once it was written.\n\nRequires the `inbox:read` scope.",
        "tags": [
          "Inbox"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "inbox:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One message, or where an API send stands",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        "object": {
                          "type": "string",
                          "const": "message"
                        },
                        "thread_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "contact_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "channel": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "direction": {
                          "type": "string",
                          "enum": [
                            "inbound",
                            "outbound"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "description": "queued, sending, sent, delivered, read, failed, bounced … (inbound: received)."
                        },
                        "body": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "source": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "What wrote it: api, automation, a campaign step (null) …"
                        },
                        "campaign_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "failure": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Why it didn't go out (status failed), in customer words."
                        },
                        "opened_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "clicked_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "bounced_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "created_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "object",
                        "thread_id",
                        "contact_id",
                        "channel",
                        "direction",
                        "status",
                        "body",
                        "source",
                        "campaign_id",
                        "failure",
                        "opened_at",
                        "clicked_at",
                        "bounced_at",
                        "created_at"
                      ],
                      "additionalProperties": false,
                      "description": "One message on a thread."
                    },
                    {
                      "type": "object",
                      "properties": {
                        "object": {
                          "type": "string",
                          "const": "send_request"
                        },
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        "kind": {
                          "type": "string",
                          "enum": [
                            "message",
                            "call"
                          ]
                        },
                        "channel": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "contact_id": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "state": {
                          "type": "string",
                          "enum": [
                            "awaiting_approval",
                            "skipped",
                            "queued",
                            "blocked",
                            "sent",
                            "failed"
                          ],
                          "description": "Where it stands."
                        },
                        "reason": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Why it was blocked (suppressed, no_consent, do_not_contact, journey_ended …)."
                        },
                        "created_at": {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        "message": {
                          "description": "The message, once it was written to the thread.",
                          "anyOf": [
                            {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                  "description": "An id (UUID)."
                                },
                                "object": {
                                  "type": "string",
                                  "const": "message"
                                },
                                "thread_id": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "uuid",
                                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                      "description": "An id (UUID)."
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "contact_id": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "uuid",
                                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                      "description": "An id (UUID)."
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "channel": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "direction": {
                                  "type": "string",
                                  "enum": [
                                    "inbound",
                                    "outbound"
                                  ]
                                },
                                "status": {
                                  "type": "string",
                                  "description": "queued, sending, sent, delivered, read, failed, bounced … (inbound: received)."
                                },
                                "body": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "source": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "What wrote it: api, automation, a campaign step (null) …"
                                },
                                "campaign_id": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "uuid",
                                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                      "description": "An id (UUID)."
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "failure": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "Why it didn't go out (status failed), in customer words."
                                },
                                "opened_at": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "description": "RFC 3339 UTC timestamp with milliseconds."
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "clicked_at": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "description": "RFC 3339 UTC timestamp with milliseconds."
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "bounced_at": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "description": "RFC 3339 UTC timestamp with milliseconds."
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "created_at": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "description": "RFC 3339 UTC timestamp with milliseconds."
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                }
                              },
                              "required": [
                                "id",
                                "object",
                                "thread_id",
                                "contact_id",
                                "channel",
                                "direction",
                                "status",
                                "body",
                                "source",
                                "campaign_id",
                                "failure",
                                "opened_at",
                                "clicked_at",
                                "bounced_at",
                                "created_at"
                              ],
                              "additionalProperties": false,
                              "description": "One message on a thread."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "call_id": {
                          "description": "The call, once it was placed (GET /calls/{call_id}).",
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "kind",
                        "channel",
                        "contact_id",
                        "state",
                        "reason",
                        "created_at"
                      ],
                      "additionalProperties": false,
                      "description": "An API send by its request id."
                    }
                  ]
                },
                "example": {
                  "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                  "object": "message",
                  "thread_id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "channel": "email",
                  "direction": "outbound",
                  "status": "delivered",
                  "body": "Hi Maja, …",
                  "source": "api",
                  "campaign_id": null,
                  "failure": null,
                  "opened_at": null,
                  "clicked_at": null,
                  "bounced_at": null,
                  "created_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "inbox:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/nora/ask": {
      "post": {
        "operationId": "ask_nora",
        "summary": "Ask Nora a question",
        "description": "Asks Nora — the workspace's AI colleague — a question and returns her answer, with the real data she shows when the question is about it (replies, numbers, connections, people, post engagement, what works in your ads) — cut to what this key's scopes may read (`data_needs_scope` names the scope otherwise). Nora answers from the workspace's data, the way she does in the app. Asking NEVER starts work, sends, approves, builds or changes anything; to have Nora do something, give her a task (POST /nora/runs). Asked to make or find ads, she says she makes them inside a plan (`ads_by_plan: true`; POST /briefs). The answer follows Accept-Language. Up to 10 questions a minute per key and 200 an hour per workspace.\n\nRequires the `nora:ask` scope.",
        "tags": [
          "Nora"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "nora:ask"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "question": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000,
                    "description": "The question, in plain words."
                  }
                },
                "required": [
                  "question"
                ],
                "additionalProperties": false
              },
              "example": {
                "question": "How many people replied this week?"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ask Nora a question",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "nora_answer"
                    },
                    "question": {
                      "type": "string"
                    },
                    "answer": {
                      "type": "string",
                      "description": "Nora's answer, in the language of Accept-Language."
                    },
                    "ads_by_plan": {
                      "type": "boolean",
                      "description": "true when the question asked Nora to make or find ads: she makes ads only inside a plan (POST /briefs)."
                    },
                    "data": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "replies",
                                "insight",
                                "connections",
                                "people",
                                "leads",
                                "engagement",
                                "performance",
                                "open"
                              ]
                            }
                          },
                          "required": [
                            "type"
                          ],
                          "additionalProperties": {}
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The real data Nora showed with her answer (the same view the phone app draws: replies, numbers, connections, people, post engagement, what works, or a page to open)."
                    },
                    "data_needs_scope": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "When Nora showed data this key may not read: the scope it would need."
                    }
                  },
                  "required": [
                    "object",
                    "question",
                    "answer",
                    "ads_by_plan",
                    "data",
                    "data_needs_scope"
                  ],
                  "additionalProperties": false,
                  "description": "Nora's answer to a question. Asking never starts work, sends, approves or changes anything."
                },
                "example": {
                  "object": "nora_answer",
                  "question": "How many people replied this week?",
                  "answer": "Nine people wrote back this week — six on email and three on WhatsApp. Two of them asked for a call.",
                  "ads_by_plan": false,
                  "data": {
                    "type": "replies",
                    "items": [
                      {
                        "thread_id": "1f2e3d4c-5b6a-4978-8a9b-0c1d2e3f4a5b",
                        "name": "Anna Berg",
                        "company": "Nordic Dental",
                        "channel": "email",
                        "subject": "Re: winter staffing",
                        "body": "Sounds good — can you call me Thursday?",
                        "time_ago": "2 h ago",
                        "unread": true
                      }
                    ]
                  },
                  "data_needs_scope": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "nora:ask",
        "x-norreach-action": "nora.ask",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/nora/runs": {
      "get": {
        "operationId": "list_nora_runs",
        "summary": "List Nora's tasks",
        "description": "The tasks given to Nora (from the app, the phone or the API), newest first, with their status. Filter by `status`.\n\nRequires the `nora:run` scope (reaches people, spends or publishes).",
        "tags": [
          "Nora"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "nora:run"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "planning",
                "running",
                "waiting_approval",
                "done",
                "failed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List Nora's tasks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "nora_run"
                          },
                          "goal": {
                            "type": "string",
                            "description": "What Nora was asked to do."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "planning",
                              "running",
                              "waiting_approval",
                              "done",
                              "failed"
                            ],
                            "description": "planning → running → waiting_approval ↔ running → done (or failed)."
                          },
                          "done": {
                            "type": "boolean"
                          },
                          "autonomy": {
                            "type": "string",
                            "enum": [
                              "ask",
                              "inherit",
                              "auto"
                            ],
                            "description": "\"ask\" = every step that sends, calls or publishes waits for an approval (always for runs started through the API)."
                          },
                          "created_by": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "started_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "finished_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "goal",
                          "status",
                          "done",
                          "autonomy",
                          "created_by",
                          "created_at",
                          "started_at",
                          "finished_at"
                        ],
                        "additionalProperties": false,
                        "description": "A task given to Nora."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                      "object": "nora_run",
                      "goal": "Follow up with everyone who downloaded the winter staffing guide",
                      "status": "waiting_approval",
                      "done": false,
                      "autonomy": "ask",
                      "created_by": "0b1c2d3e-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
                      "created_at": "2026-11-05T09:12:33.120Z",
                      "started_at": "2026-11-05T09:12:35.000Z",
                      "finished_at": null
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "nora:run",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "start_nora_run",
        "summary": "Give Nora a task",
        "description": "Gives Nora a task in plain words (\"follow up with everyone who downloaded the guide\") — the same as the app's Nora console. She plans it and works through it; follow it with GET /nora/runs/{id}. Through the API a task always asks first: every step that sends, calls or publishes waits in Approvals (GET /approvals; decide with POST /approvals/{key}/approve). Outreach paused → 409. Nora makes ads only inside a plan: a goal to make, find or publish ads is refused with 422 ads_by_plan and the way that does work (`use`: POST /briefs); changing a live ad or reading ad results isn't a task either (the answer says where). Owners, admins and managers. Up to 30 tasks an hour per workspace. `dry_run=true` checks it and starts nothing.\n\nRequires the `nora:run` scope (reaches people, spends or publishes).",
        "tags": [
          "Nora"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "nora:run"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "goal": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000,
                    "description": "What Nora should do, in plain words."
                  }
                },
                "required": [
                  "goal"
                ],
                "additionalProperties": false
              },
              "example": {
                "goal": "Follow up with everyone who downloaded the winter staffing guide"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Give Nora a task",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        "object": {
                          "type": "string",
                          "const": "nora_run"
                        },
                        "goal": {
                          "type": "string",
                          "description": "What Nora was asked to do."
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "draft",
                            "planning",
                            "running",
                            "waiting_approval",
                            "done",
                            "failed"
                          ],
                          "description": "planning → running → waiting_approval ↔ running → done (or failed)."
                        },
                        "done": {
                          "type": "boolean"
                        },
                        "autonomy": {
                          "type": "string",
                          "enum": [
                            "ask",
                            "inherit",
                            "auto"
                          ],
                          "description": "\"ask\" = every step that sends, calls or publishes waits for an approval (always for runs started through the API)."
                        },
                        "created_by": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "created_at": {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        "started_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "finished_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "steps": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              "index": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "action": {
                                "type": "string",
                                "description": "What the step does (draft_message, schedule_send, place_call, create_campaign …; other = anything else)."
                              },
                              "status": {
                                "type": "string"
                              },
                              "needs_approval": {
                                "type": "boolean"
                              },
                              "approval_key": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "When the step waits for an OK: its key in the Approvals queue (POST /approvals/{key}/approve)."
                              },
                              "created_at": {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              }
                            },
                            "required": [
                              "id",
                              "index",
                              "action",
                              "status",
                              "needs_approval",
                              "approval_key",
                              "created_at"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "messages": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              "role": {
                                "type": "string",
                                "enum": [
                                  "nora",
                                  "you"
                                ]
                              },
                              "text": {
                                "type": "string"
                              },
                              "created_at": {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              }
                            },
                            "required": [
                              "id",
                              "role",
                              "text",
                              "created_at"
                            ],
                            "additionalProperties": false
                          },
                          "description": "What was said (the last 50)."
                        },
                        "waiting_for_approval": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Approval keys this task waits on."
                        }
                      },
                      "required": [
                        "id",
                        "object",
                        "goal",
                        "status",
                        "done",
                        "autonomy",
                        "created_by",
                        "created_at",
                        "started_at",
                        "finished_at",
                        "steps",
                        "messages",
                        "waiting_for_approval"
                      ],
                      "additionalProperties": false,
                      "description": "A task given to Nora, with its steps and what was said."
                    },
                    {
                      "type": "object",
                      "properties": {
                        "object": {
                          "type": "string",
                          "const": "nora_run"
                        },
                        "id": {
                          "type": "null"
                        },
                        "dry_run": {
                          "type": "boolean",
                          "const": true
                        },
                        "goal": {
                          "type": "string"
                        },
                        "would": {
                          "type": "object",
                          "properties": {
                            "start": {
                              "type": "boolean",
                              "const": true
                            },
                            "autonomy": {
                              "type": "string",
                              "const": "ask"
                            }
                          },
                          "required": [
                            "start",
                            "autonomy"
                          ],
                          "additionalProperties": false,
                          "description": "What would happen: a task is started, and every step that sends waits for an approval."
                        }
                      },
                      "required": [
                        "object",
                        "id",
                        "dry_run",
                        "goal",
                        "would"
                      ],
                      "additionalProperties": false
                    }
                  ]
                },
                "example": {
                  "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                  "object": "nora_run",
                  "goal": "Follow up with everyone who downloaded the winter staffing guide",
                  "status": "planning",
                  "done": false,
                  "autonomy": "ask",
                  "created_by": "0b1c2d3e-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
                  "created_at": "2026-11-05T09:12:33.120Z",
                  "started_at": null,
                  "finished_at": null,
                  "steps": [],
                  "messages": [],
                  "waiting_for_approval": []
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `outreach_paused` — Outreach is paused for this workspace. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request. · `ads_by_plan` — Nora makes ads only inside a plan.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "nora:run",
        "x-norreach-action": "nora.run",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/nora/runs/{id}": {
      "get": {
        "operationId": "get_nora_run",
        "summary": "Get a Nora task",
        "description": "One task: its status, its steps (what each does, whether it waits for an OK and that approval's key), what Nora and you said (the last 50 messages), and the approvals it waits on. Through the API a task always asks first: every step that sends, calls or publishes waits in Approvals (GET /approvals; decide with POST /approvals/{key}/approve).\n\nRequires the `nora:run` scope (reaches people, spends or publishes).",
        "tags": [
          "Nora"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "nora:run"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a Nora task",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "nora_run"
                    },
                    "goal": {
                      "type": "string",
                      "description": "What Nora was asked to do."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "planning",
                        "running",
                        "waiting_approval",
                        "done",
                        "failed"
                      ],
                      "description": "planning → running → waiting_approval ↔ running → done (or failed)."
                    },
                    "done": {
                      "type": "boolean"
                    },
                    "autonomy": {
                      "type": "string",
                      "enum": [
                        "ask",
                        "inherit",
                        "auto"
                      ],
                      "description": "\"ask\" = every step that sends, calls or publishes waits for an approval (always for runs started through the API)."
                    },
                    "created_by": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "started_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "finished_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "steps": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "index": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "action": {
                            "type": "string",
                            "description": "What the step does (draft_message, schedule_send, place_call, create_campaign …; other = anything else)."
                          },
                          "status": {
                            "type": "string"
                          },
                          "needs_approval": {
                            "type": "boolean"
                          },
                          "approval_key": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "When the step waits for an OK: its key in the Approvals queue (POST /approvals/{key}/approve)."
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          }
                        },
                        "required": [
                          "id",
                          "index",
                          "action",
                          "status",
                          "needs_approval",
                          "approval_key",
                          "created_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "messages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "nora",
                              "you"
                            ]
                          },
                          "text": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          }
                        },
                        "required": [
                          "id",
                          "role",
                          "text",
                          "created_at"
                        ],
                        "additionalProperties": false
                      },
                      "description": "What was said (the last 50)."
                    },
                    "waiting_for_approval": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Approval keys this task waits on."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "goal",
                    "status",
                    "done",
                    "autonomy",
                    "created_by",
                    "created_at",
                    "started_at",
                    "finished_at",
                    "steps",
                    "messages",
                    "waiting_for_approval"
                  ],
                  "additionalProperties": false,
                  "description": "A task given to Nora, with its steps and what was said."
                },
                "example": {
                  "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                  "object": "nora_run",
                  "goal": "Follow up with everyone who downloaded the winter staffing guide",
                  "status": "waiting_approval",
                  "done": false,
                  "autonomy": "ask",
                  "created_by": "0b1c2d3e-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
                  "created_at": "2026-11-05T09:12:33.120Z",
                  "started_at": "2026-11-05T09:12:35.000Z",
                  "finished_at": null,
                  "steps": [
                    {
                      "id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                      "index": 0,
                      "action": "draft_message",
                      "status": "done",
                      "needs_approval": false,
                      "approval_key": null,
                      "created_at": "2026-11-05T09:12:40.000Z"
                    },
                    {
                      "id": "6f7a8b9c-0d1e-4f2a-9b3c-4d5e6f7a8b9c",
                      "index": 1,
                      "action": "schedule_send",
                      "status": "waiting_approval",
                      "needs_approval": true,
                      "approval_key": "run_gate:7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                      "created_at": "2026-11-05T09:12:41.000Z"
                    }
                  ],
                  "messages": [
                    {
                      "id": "8b9c0d1e-2f3a-4b4c-9d5e-6f7a8b9c0d1e",
                      "role": "you",
                      "text": "Follow up with everyone who downloaded the winter staffing guide",
                      "created_at": "2026-11-05T09:12:33.120Z"
                    },
                    {
                      "id": "9c0d1e2f-3a4b-4c5d-8e6f-7a8b9c0d1e2f",
                      "role": "nora",
                      "text": "I drafted a short follow-up for the 42 people who downloaded it. It waits for your OK before it goes out.",
                      "created_at": "2026-11-05T09:12:41.500Z"
                    }
                  ],
                  "waiting_for_approval": [
                    "run_gate:7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "nora:run",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/number-verifications": {
      "get": {
        "operationId": "list_number_verifications",
        "summary": "List business verifications",
        "description": "The workspace's business verifications for buying numbers in countries that ask for documents: country, number type, status (`draft`, `submitted`, `approved`, `declined`, `expired`), why it was declined, and what was sent — labels and file names only, never the values or the files. Pending ones are checked again while you read.\n\nRequires the `numbers:read` scope.",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "numbers:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List business verifications",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "number_verification"
                          },
                          "country": {
                            "type": "string"
                          },
                          "number_type": {
                            "type": "string",
                            "enum": [
                              "local",
                              "mobile",
                              "toll_free",
                              "national",
                              "shared_cost"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "submitted",
                              "approved",
                              "declined",
                              "expired"
                            ]
                          },
                          "decline_reason": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "submitted_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "decided_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "checked_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "fields": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "label": {
                                  "type": "string"
                                },
                                "kind": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "label",
                                "kind"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "documents": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "label": {
                                  "type": "string"
                                },
                                "file_name": {
                                  "type": "string"
                                },
                                "size": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                "content_type": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "label",
                                "file_name",
                                "size",
                                "content_type"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "country",
                          "number_type",
                          "status",
                          "decline_reason",
                          "submitted_at",
                          "decided_at",
                          "checked_at",
                          "created_at",
                          "fields",
                          "documents"
                        ],
                        "additionalProperties": false,
                        "description": "A business verification: what was sent (labels and file names only — never the values or files) and where it stands."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "8b9c0d1e-2f3a-4b4c-9d5e-6f7a8b9c0d1e",
                      "object": "number_verification",
                      "country": "SE",
                      "number_type": "local",
                      "status": "submitted",
                      "decline_reason": null,
                      "submitted_at": "2026-11-05T09:00:00.000Z",
                      "decided_at": null,
                      "checked_at": "2026-11-05T09:00:00.000Z",
                      "created_at": "2026-11-05T08:59:58.000Z",
                      "fields": [
                        {
                          "label": "Company registration number",
                          "kind": "text"
                        },
                        {
                          "label": "Address matching the DID area code",
                          "kind": "address"
                        },
                        {
                          "label": "Proof of address",
                          "kind": "document"
                        }
                      ],
                      "documents": [
                        {
                          "label": "Proof of address",
                          "file_name": "utility-bill.pdf",
                          "size": 182311,
                          "content_type": "application/pdf"
                        }
                      ]
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "numbers:read",
        "x-norreach-action": null,
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "submit_number_verification",
        "summary": "Submit a business verification",
        "description": "Sends the workspace's business details and documents for a country and number type for review, exactly as the Phone numbers page does: the requirements are read again on the server, every field is checked, one submission per country and type runs at a time (409 while one is running or approved), the documents go straight to review and only their names are kept. Answer each field by its id from GET /number-verifications/requirements: `values` for text, `addresses` for addresses, `documents` (base64, PDF / JPG / PNG — all together at most about 3 MB through the API; larger scans go through the app). `dry_run=true` checks everything and sends nothing. Owners, admins and managers.\n\nRequires the `numbers:verify` scope (reaches people, spends or publishes).",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "numbers:verify"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "country": {
                    "type": "string",
                    "pattern": "^[A-Za-z]{2}$",
                    "description": "ISO 3166-1 alpha-2."
                  },
                  "number_type": {
                    "type": "string",
                    "enum": [
                      "local",
                      "mobile",
                      "toll_free",
                      "national",
                      "shared_cost"
                    ]
                  },
                  "values": {
                    "default": {},
                    "description": "Text answers by field id.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[A-Za-z0-9_-]{1,80}$"
                    },
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 500
                    }
                  },
                  "addresses": {
                    "default": {},
                    "description": "Addresses by field id.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[A-Za-z0-9_-]{1,80}$"
                    },
                    "additionalProperties": {
                      "type": "object",
                      "properties": {
                        "business_name": {
                          "type": "string",
                          "maxLength": 120
                        },
                        "first_name": {
                          "type": "string",
                          "maxLength": 60
                        },
                        "last_name": {
                          "type": "string",
                          "maxLength": 60
                        },
                        "street_address": {
                          "type": "string",
                          "maxLength": 120
                        },
                        "extended_address": {
                          "type": "string",
                          "maxLength": 120
                        },
                        "locality": {
                          "type": "string",
                          "maxLength": 80
                        },
                        "administrative_area": {
                          "type": "string",
                          "maxLength": 80
                        },
                        "postal_code": {
                          "type": "string",
                          "maxLength": 20
                        },
                        "country_code": {
                          "type": "string",
                          "minLength": 2,
                          "maxLength": 2
                        }
                      },
                      "required": [
                        "business_name",
                        "first_name",
                        "last_name",
                        "street_address",
                        "locality",
                        "postal_code",
                        "country_code"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "confirm_addresses": {
                    "default": [],
                    "description": "Field ids of addresses to send as entered after the address check suggested a change.",
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^[A-Za-z0-9_-]{1,80}$"
                    }
                  },
                  "documents": {
                    "default": {},
                    "description": "Documents by field id (PDF, JPG or PNG). All files together at most about 3 MB through the API — larger scans go through the app.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[A-Za-z0-9_-]{1,80}$"
                    },
                    "additionalProperties": {
                      "type": "object",
                      "properties": {
                        "file_name": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 200
                        },
                        "content_type": {
                          "type": "string",
                          "enum": [
                            "application/pdf",
                            "image/jpeg",
                            "image/png"
                          ]
                        },
                        "data_base64": {
                          "type": "string",
                          "minLength": 4,
                          "description": "The file, base64."
                        }
                      },
                      "required": [
                        "file_name",
                        "content_type",
                        "data_base64"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "country",
                  "number_type"
                ],
                "additionalProperties": false
              },
              "example": {
                "country": "SE",
                "number_type": "local",
                "values": {
                  "req-company-number": "556677-8899"
                },
                "addresses": {
                  "req-address": {
                    "business_name": "Example Care AB",
                    "first_name": "Anna",
                    "last_name": "Berg",
                    "street_address": "Storgatan 1",
                    "locality": "Stockholm",
                    "postal_code": "11122",
                    "country_code": "SE"
                  }
                },
                "documents": {
                  "req-proof": {
                    "file_name": "utility-bill.pdf",
                    "content_type": "application/pdf",
                    "data_base64": "JVBERi0xLjcK…"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Submit a business verification",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "number_verification_submission"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "verification": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            "object": {
                              "type": "string",
                              "const": "number_verification"
                            },
                            "country": {
                              "type": "string"
                            },
                            "number_type": {
                              "type": "string",
                              "enum": [
                                "local",
                                "mobile",
                                "toll_free",
                                "national",
                                "shared_cost"
                              ]
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "draft",
                                "submitted",
                                "approved",
                                "declined",
                                "expired"
                              ]
                            },
                            "decline_reason": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "submitted_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "decided_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "checked_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "created_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "fields": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "label": {
                                    "type": "string"
                                  },
                                  "kind": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "label",
                                  "kind"
                                ],
                                "additionalProperties": false
                              }
                            },
                            "documents": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "label": {
                                    "type": "string"
                                  },
                                  "file_name": {
                                    "type": "string"
                                  },
                                  "size": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "content_type": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "label",
                                  "file_name",
                                  "size",
                                  "content_type"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "id",
                            "object",
                            "country",
                            "number_type",
                            "status",
                            "decline_reason",
                            "submitted_at",
                            "decided_at",
                            "checked_at",
                            "created_at",
                            "fields",
                            "documents"
                          ],
                          "additionalProperties": false,
                          "description": "A business verification: what was sent (labels and file names only — never the values or files) and where it stands."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "dry_run",
                    "verification",
                    "note"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "number_verification_submission",
                  "dry_run": false,
                  "verification": {
                    "id": "8b9c0d1e-2f3a-4b4c-9d5e-6f7a8b9c0d1e",
                    "object": "number_verification",
                    "country": "SE",
                    "number_type": "local",
                    "status": "submitted",
                    "decline_reason": null,
                    "submitted_at": "2026-11-05T09:00:00.000Z",
                    "decided_at": null,
                    "checked_at": "2026-11-05T09:00:00.000Z",
                    "created_at": "2026-11-05T08:59:58.000Z",
                    "fields": [
                      {
                        "label": "Company registration number",
                        "kind": "text"
                      },
                      {
                        "label": "Address matching the DID area code",
                        "kind": "address"
                      },
                      {
                        "label": "Proof of address",
                        "kind": "document"
                      }
                    ],
                    "documents": [
                      {
                        "label": "Proof of address",
                        "file_name": "utility-bill.pdf",
                        "size": 182311,
                        "content_type": "application/pdf"
                      }
                    ]
                  },
                  "note": "Sent for review. The decision usually takes a few working days — follow it with GET /number-verifications."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "numbers:verify",
        "x-norreach-action": "numbers.verify",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/number-verifications/requirements": {
      "get": {
        "operationId": "get_number_verification_requirements",
        "summary": "What a business verification needs",
        "description": "What numbers of a `country` and `number_type` ask for before they can be bought: each field (text, address or document) with its id, label, description, example and criteria, read live. `required: false` = nothing is needed. Also the workspace's own verification for it, if there is one.\n\nRequires the `numbers:read` scope.",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "numbers:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$"
            }
          },
          {
            "name": "number_type",
            "in": "query",
            "required": false,
            "schema": {
              "default": "local",
              "type": "string",
              "enum": [
                "local",
                "mobile",
                "toll_free",
                "national",
                "shared_cost"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "What a business verification needs",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "verification_requirements"
                    },
                    "country": {
                      "type": "string"
                    },
                    "number_type": {
                      "type": "string",
                      "enum": [
                        "local",
                        "mobile",
                        "toll_free",
                        "national",
                        "shared_cost"
                      ]
                    },
                    "configured": {
                      "type": "boolean",
                      "description": "False while business verification isn't available on this workspace."
                    },
                    "required": {
                      "type": "boolean",
                      "description": "False = numbers of this country and type need no verification."
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Send the value under this id."
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "text",
                              "address",
                              "document"
                            ]
                          },
                          "label": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "example": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "criteria": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "input": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "min_length": {
                                    "anyOf": [
                                      {
                                        "type": "integer",
                                        "minimum": -9007199254740991,
                                        "maximum": 9007199254740991
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "max_length": {
                                    "anyOf": [
                                      {
                                        "type": "integer",
                                        "minimum": -9007199254740991,
                                        "maximum": 9007199254740991
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "options": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  },
                                  "characters": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  }
                                },
                                "required": [
                                  "type",
                                  "min_length",
                                  "max_length",
                                  "options",
                                  "characters"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "file": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "accept": {
                                    "type": "string"
                                  },
                                  "max_bytes": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  }
                                },
                                "required": [
                                  "accept",
                                  "max_bytes"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "kind",
                          "label",
                          "description",
                          "example",
                          "criteria",
                          "input",
                          "file"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "verification": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            "object": {
                              "type": "string",
                              "const": "number_verification"
                            },
                            "country": {
                              "type": "string"
                            },
                            "number_type": {
                              "type": "string",
                              "enum": [
                                "local",
                                "mobile",
                                "toll_free",
                                "national",
                                "shared_cost"
                              ]
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "draft",
                                "submitted",
                                "approved",
                                "declined",
                                "expired"
                              ]
                            },
                            "decline_reason": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "submitted_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "decided_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "checked_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "created_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "fields": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "label": {
                                    "type": "string"
                                  },
                                  "kind": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "label",
                                  "kind"
                                ],
                                "additionalProperties": false
                              }
                            },
                            "documents": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "label": {
                                    "type": "string"
                                  },
                                  "file_name": {
                                    "type": "string"
                                  },
                                  "size": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "content_type": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "label",
                                  "file_name",
                                  "size",
                                  "content_type"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "id",
                            "object",
                            "country",
                            "number_type",
                            "status",
                            "decline_reason",
                            "submitted_at",
                            "decided_at",
                            "checked_at",
                            "created_at",
                            "fields",
                            "documents"
                          ],
                          "additionalProperties": false,
                          "description": "A business verification: what was sent (labels and file names only — never the values or files) and where it stands."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The workspace's own verification for this country and type, if any."
                    },
                    "limits": {
                      "type": "object",
                      "properties": {
                        "max_upload_bytes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "document_types": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": [
                        "max_upload_bytes",
                        "document_types"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "object",
                    "country",
                    "number_type",
                    "configured",
                    "required",
                    "fields",
                    "verification",
                    "limits"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "verification_requirements",
                  "country": "SE",
                  "number_type": "local",
                  "configured": true,
                  "required": true,
                  "fields": [
                    {
                      "id": "req-company-number",
                      "kind": "text",
                      "label": "Company registration number",
                      "description": "The company's registration number.",
                      "example": "556677-8899",
                      "criteria": [
                        "10–11 characters"
                      ],
                      "input": {
                        "type": "text",
                        "min_length": 10,
                        "max_length": 11,
                        "options": [],
                        "characters": "0123456789-"
                      },
                      "file": null
                    },
                    {
                      "id": "req-proof",
                      "kind": "document",
                      "label": "Proof of address",
                      "description": "A utility bill showing the address.",
                      "example": null,
                      "criteria": [
                        "Less than 3 months old"
                      ],
                      "input": null,
                      "file": {
                        "accept": ".pdf,.jpg,.jpeg,.png",
                        "max_bytes": 4000000
                      }
                    }
                  ],
                  "verification": null,
                  "limits": {
                    "max_upload_bytes": 4000000,
                    "document_types": [
                      "application/pdf",
                      "image/jpeg",
                      "image/png"
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "numbers:read",
        "x-norreach-action": null,
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "get_openapi",
        "summary": "The OpenAPI document",
        "description": "This API as an OpenAPI 3.1 document, generated from the same definitions the server runs. Import it into your tools or generate a client from it.\n\nAny valid key.",
        "tags": [
          "Workspace"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": []
          }
        ],
        "responses": {
          "200": {
            "description": "The OpenAPI document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "openapi": {
                      "type": "string",
                      "const": "3.1.0"
                    }
                  },
                  "required": [
                    "openapi"
                  ],
                  "additionalProperties": {},
                  "description": "An OpenAPI 3.1 document."
                },
                "example": {
                  "openapi": "3.1.0",
                  "info": {
                    "title": "NorReach API",
                    "version": "1.0.0"
                  },
                  "paths": {}
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "any",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/pages": {
      "get": {
        "operationId": "list_pages",
        "summary": "List pages",
        "description": "The workspace's landing pages, newest first (up to 200): status, address, and whether one waits for approval or for NorReach's look.\n\nRequires the `pages:read` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "site_id",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List pages",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "page"
                          },
                          "site_id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "slug": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "description": "draft, in_review, published, unpublished or taken_down."
                          },
                          "title": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string"
                          },
                          "plan_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The plan Nora made the page in."
                          },
                          "waiting_for_approval": {
                            "type": "boolean"
                          },
                          "waiting_for_staff": {
                            "type": "boolean",
                            "description": "Approved, and NorReach takes a quick look before it goes live."
                          },
                          "published_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "site_id",
                          "slug",
                          "status",
                          "title",
                          "url",
                          "plan_id",
                          "waiting_for_approval",
                          "waiting_for_staff",
                          "published_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                      "object": "page",
                      "site_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                      "slug": "nurses-stockholm",
                      "status": "published",
                      "title": "Nurses when you need them",
                      "url": "https://acme.norreach.page/nurses-stockholm",
                      "plan_id": null,
                      "waiting_for_approval": false,
                      "waiting_for_staff": false,
                      "published_at": "2026-11-04T09:12:33.120Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/pages/{id}": {
      "get": {
        "operationId": "get_page",
        "summary": "One page",
        "description": "A landing page with its working copy (`draft`) and which version is live, waiting for approval or waiting for NorReach.\n\nRequires the `pages:read` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "page"
                    },
                    "site_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "slug": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "description": "draft, in_review, published, unpublished or taken_down."
                    },
                    "title": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "plan_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The plan Nora made the page in."
                    },
                    "waiting_for_approval": {
                      "type": "boolean"
                    },
                    "waiting_for_staff": {
                      "type": "boolean",
                      "description": "Approved, and NorReach takes a quick look before it goes live."
                    },
                    "published_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "draft": {
                      "description": "The working copy (the same content format the editor saves)."
                    },
                    "draft_base_version_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Send it back with PATCH /pages/{id}/draft, so a newer edit is never overwritten."
                    },
                    "published_version_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "review_version_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "pending_version_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "noindex": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "site_id",
                    "slug",
                    "status",
                    "title",
                    "url",
                    "plan_id",
                    "waiting_for_approval",
                    "waiting_for_staff",
                    "published_at",
                    "draft",
                    "draft_base_version_id",
                    "published_version_id",
                    "review_version_id",
                    "pending_version_id",
                    "noindex"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                  "object": "page",
                  "site_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                  "slug": "nurses-stockholm",
                  "status": "published",
                  "title": "Nurses when you need them",
                  "url": "https://acme.norreach.page/nurses-stockholm",
                  "plan_id": null,
                  "waiting_for_approval": false,
                  "waiting_for_staff": false,
                  "published_at": "2026-11-04T09:12:33.120Z",
                  "draft": {
                    "schema": 1,
                    "seo": {
                      "title": "Nurses",
                      "description": "Within 48 hours."
                    },
                    "blocks": []
                  },
                  "draft_base_version_id": null,
                  "published_version_id": null,
                  "review_version_id": null,
                  "pending_version_id": null,
                  "noindex": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/pages/{id}/analytics": {
      "get": {
        "operationId": "get_page_analytics",
        "summary": "A page's analytics",
        "description": "Views, visitors, clicks, form starts, leads and bookings over the last 7, 30 or 90 days: totals, per day, per ad network, and by referrer, campaign, country and device.\n\nRequires the `pages:read` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "default": "30",
              "type": "string",
              "enum": [
                "7",
                "30",
                "90"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page's analytics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "page_analytics"
                    },
                    "page_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "days": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "from": {
                      "type": "string"
                    },
                    "totals": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "anyOf": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      }
                    },
                    "daily": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "number"
                            }
                          ]
                        }
                      }
                    },
                    "by_network": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "number"
                            }
                          ]
                        }
                      }
                    },
                    "breakdowns": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        }
                      }
                    }
                  },
                  "required": [
                    "object",
                    "page_id",
                    "days",
                    "from",
                    "totals",
                    "daily",
                    "by_network",
                    "breakdowns"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "page_analytics",
                  "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                  "days": 30,
                  "from": "2026-10-06",
                  "totals": {
                    "views": 1200,
                    "visitors": 900,
                    "cta_clicks": 210,
                    "form_starts": 80,
                    "submissions": 42,
                    "bookings": 6,
                    "conversion_rate": 0.0467
                  },
                  "daily": [
                    {
                      "day": "2026-11-04",
                      "views": 40,
                      "visitors": 31,
                      "cta_clicks": 7,
                      "form_starts": 3,
                      "submissions": 2,
                      "bookings": 0
                    }
                  ],
                  "by_network": [
                    {
                      "network": "meta",
                      "views": 800,
                      "visitors": 600,
                      "cta_clicks": 150,
                      "form_starts": 60,
                      "submissions": 30,
                      "bookings": 4
                    }
                  ],
                  "breakdowns": {
                    "country": [
                      {
                        "value": "SE",
                        "views": 1000,
                        "visitors": 760,
                        "leads": 38,
                        "share": 0.84
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/pages/{id}/draft": {
      "patch": {
        "operationId": "update_page_draft",
        "summary": "Edit a page's working copy",
        "description": "Replaces the working copy with `content` (the same format GET /pages/{id} returns as `draft`). Send the `draft_base_version_id` you read, so an edit made in the meantime is never overwritten (409). Nothing is shown to visitors until a version is published.\n\nRequires the `pages:write` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  },
                  "base_version_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "content",
                  "base_version_id"
                ],
                "additionalProperties": false
              },
              "example": {
                "content": {
                  "schema": 1,
                  "seo": {
                    "title": "Nurses",
                    "description": "Within 48 hours."
                  },
                  "blocks": []
                },
                "base_version_id": null
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Edit a page's working copy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "draft"
                    },
                    "page_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "saved_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "object",
                    "page_id",
                    "saved_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "draft",
                  "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                  "saved_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:write",
        "x-norreach-action": "pages.edit",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/pages/{id}/leads": {
      "get": {
        "operationId": "list_page_leads",
        "summary": "A page's form leads",
        "description": "Form submissions from one landing page, newest first.\n\nRequires the `pages:read` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "default": "30",
              "type": "string",
              "enum": [
                "7",
                "30",
                "90",
                "all"
              ]
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "spam",
            "in": "query",
            "required": false,
            "schema": {
              "default": "false",
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page's form leads",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "lead"
                          },
                          "page_id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "contact_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "network": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The ad network the visitor came from, if any."
                          },
                          "ad_key": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "campaign": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "marketing_opt_in": {
                            "type": "string",
                            "enum": [
                              "yes",
                              "no",
                              "not_asked"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "email": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "phone": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "answers": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "key": {
                                  "type": "string"
                                },
                                "label": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "value": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "boolean"
                                    }
                                  ]
                                }
                              },
                              "required": [
                                "key",
                                "label",
                                "value"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "page_title": {
                            "type": "string"
                          },
                          "page_url": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "page_id",
                          "contact_id",
                          "status",
                          "created_at",
                          "network",
                          "ad_key",
                          "campaign",
                          "marketing_opt_in",
                          "name",
                          "email",
                          "phone",
                          "answers",
                          "page_title",
                          "page_url"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "6b7c8d9e-0f1a-4b2c-9d3e-4f5a6b7c8d9e",
                      "object": "lead",
                      "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                      "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                      "status": "new",
                      "created_at": "2026-11-04T09:12:33.120Z",
                      "network": "meta",
                      "ad_key": null,
                      "campaign": "november",
                      "marketing_opt_in": "yes",
                      "name": "Maja Lind",
                      "email": "maja.lind@example.com",
                      "phone": null,
                      "answers": [
                        {
                          "key": "role",
                          "label": "Role",
                          "value": "Nurse"
                        }
                      ],
                      "page_title": "Nurses when you need them",
                      "page_url": "https://acme.norreach.page/nurses-stockholm"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/pages/{id}/preview-link": {
      "get": {
        "operationId": "get_page_preview_link",
        "summary": "A preview link",
        "description": "A 15-minute link that shows the working copy (or `version`) on the page's own address, for a look before anything is published. Needs pages:write, like the editor's preview.\n\nRequires the `pages:write` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "version",
            "in": "query",
            "required": false,
            "schema": {
              "default": "draft",
              "anyOf": [
                {
                  "type": "string",
                  "const": "draft"
                },
                {
                  "type": "string",
                  "format": "uuid",
                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                  "description": "An id (UUID)."
                }
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A preview link",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "preview_link"
                    },
                    "page_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "url": {
                      "type": "string"
                    },
                    "expires_in": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "object",
                    "page_id",
                    "url",
                    "expires_in"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "preview_link",
                  "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                  "url": "https://acme.norreach.page/__preview/…",
                  "expires_in": 900
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:write",
        "x-norreach-action": "pages.edit",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/pages/{id}/publish": {
      "post": {
        "operationId": "publish_page",
        "summary": "Publish a page",
        "description": "Puts a version live (`version_id`; omit it to publish the working copy, an older version is a rollback). This is the key's creator saying yes. The content checks still decide: a page they block answers 422 publish_blocked with the reasons; one NorReach takes a quick look at first answers 202 with state `waiting_for_staff`. `dry_run=true` checks the page and version and changes nothing.\n\nRequires the `pages:publish` scope (reaches people, spends or publishes).",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:publish"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "version_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "version_id": "8c9d0e1f-2a3b-4c4d-9e5f-6a7b8c9d0e1f"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Publish a page",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "publish_result"
                    },
                    "page_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "version_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "state": {
                      "type": "string",
                      "enum": [
                        "published",
                        "waiting_for_staff",
                        "unpublished",
                        "dry_run"
                      ]
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "page_id",
                    "version_id",
                    "state",
                    "note"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "publish_result",
                  "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                  "version_id": "8c9d0e1f-2a3b-4c4d-9e5f-6a7b8c9d0e1f",
                  "state": "published",
                  "note": "Approved — the page is live."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request. · `publish_blocked` — This page can't be published.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:publish",
        "x-norreach-action": "pages.publish",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/pages/{id}/submit": {
      "post": {
        "operationId": "submit_page",
        "summary": "Send for approval",
        "description": "Saves the working copy as a version and puts it in the Approvals queue for a person's OK.\n\nRequires the `pages:write` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Send for approval",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "page_version_ref"
                    },
                    "page_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "version_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "created": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "page_id",
                    "version_id",
                    "created"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "page_version_ref",
                  "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                  "version_id": "8c9d0e1f-2a3b-4c4d-9e5f-6a7b8c9d0e1f",
                  "created": true
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:write",
        "x-norreach-action": "pages.edit",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/pages/{id}/unpublish": {
      "post": {
        "operationId": "unpublish_page",
        "summary": "Take a page down",
        "description": "Takes a live page down. Its versions stay; publishing again puts it back. Ads pointing at it lose their landing page — check them in the app. `dry_run=true` changes nothing.\n\nRequires the `pages:publish` scope (reaches people, spends or publishes).",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:publish"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Take a page down",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "publish_result"
                    },
                    "page_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "version_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "state": {
                      "type": "string",
                      "enum": [
                        "published",
                        "waiting_for_staff",
                        "unpublished",
                        "dry_run"
                      ]
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "page_id",
                    "version_id",
                    "state",
                    "note"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "publish_result",
                  "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                  "version_id": null,
                  "state": "unpublished",
                  "note": "The page is no longer live."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:publish",
        "x-norreach-action": "pages.publish",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/pages/{id}/versions": {
      "get": {
        "operationId": "list_page_versions",
        "summary": "A page's versions",
        "description": "The newest ten saved versions of a page, newest first, with who made each and any content checks that hold it back.\n\nRequires the `pages:read` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page's versions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "page_version"
                          },
                          "page_id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "number": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "author_kind": {
                            "type": "string",
                            "description": "Who made it: nora or user."
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "note": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "holds": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Content checks that would hold it back."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "page_id",
                          "number",
                          "author_kind",
                          "created_at",
                          "note",
                          "holds"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "8c9d0e1f-2a3b-4c4d-9e5f-6a7b8c9d0e1f",
                      "object": "page_version",
                      "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                      "number": 3,
                      "author_kind": "user",
                      "created_at": "2026-11-04T09:12:33.120Z",
                      "note": null,
                      "holds": []
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "create_page_version",
        "summary": "Save a version",
        "description": "Saves the working copy as a version (nothing new when it hasn't changed). Versions are what gets published.\n\nRequires the `pages:write` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "note": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 300
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Save a version",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "page_version_ref"
                    },
                    "page_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "version_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "created": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "page_id",
                    "version_id",
                    "created"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "page_version_ref",
                  "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                  "version_id": "8c9d0e1f-2a3b-4c4d-9e5f-6a7b8c9d0e1f",
                  "created": true
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:write",
        "x-norreach-action": "pages.edit",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/phone-numbers": {
      "get": {
        "operationId": "list_phone_numbers",
        "summary": "List phone numbers",
        "description": "The workspace's phone numbers: the number, label, country, what it can do (calls, texts), whether it's connected to AI calling and who answers incoming calls. Numbers connected from an account the workspace already had are voice only (`source: connected`). Removing a number is done in the app — never through the API.\n\nRequires the `numbers:read` scope.",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "numbers:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List phone numbers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "phone_number"
                          },
                          "number": {
                            "type": "string",
                            "description": "E.164."
                          },
                          "label": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "country": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "type": "string",
                            "description": "`active`, or `pending` while a purchase settles."
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "bought",
                              "connected"
                            ],
                            "description": "`bought` through NorReach, or `connected` from an account the workspace already had (voice only)."
                          },
                          "capabilities": {
                            "type": "object",
                            "properties": {
                              "voice": {
                                "type": "boolean"
                              },
                              "sms": {
                                "type": "boolean"
                              },
                              "mms": {
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "voice",
                              "sms",
                              "mms"
                            ],
                            "additionalProperties": false
                          },
                          "can_text": {
                            "type": "boolean",
                            "description": "Can send texts from NorReach (a bought number with SMS)."
                          },
                          "ai_calling": {
                            "type": "boolean",
                            "description": "Connected to AI calling."
                          },
                          "inbound_mode": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "ai",
                                  "menu"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Who answers incoming calls: `ai` = the AI agent, `menu` = the call menu (see GET /inbound-routing). Null for numbers that can't be switched."
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "number",
                          "label",
                          "country",
                          "status",
                          "source",
                          "capabilities",
                          "can_text",
                          "ai_calling",
                          "inbound_mode",
                          "created_at"
                        ],
                        "additionalProperties": false,
                        "description": "One of the workspace's phone numbers."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                      "object": "phone_number",
                      "number": "+46812345678",
                      "label": "Stockholm office",
                      "country": "SE",
                      "status": "active",
                      "source": "bought",
                      "capabilities": {
                        "voice": true,
                        "sms": true,
                        "mms": false
                      },
                      "can_text": true,
                      "ai_calling": true,
                      "inbound_mode": "ai",
                      "created_at": "2026-10-01T08:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "numbers:read",
        "x-norreach-action": null,
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "buy_phone_number",
        "summary": "Buy a phone number",
        "description": "Asks to buy a number from GET /phone-numbers/available, under the owner's rules: the key needs the numbers:buy scope (in no preset — tick it on purpose) and an owner's or admin's role; the workspace's DAILY LIMIT for numbers bought through the API and its MONTHLY-COST CEILING are enforced by the database, so parallel requests can't race past them (429 number_cap_reached with `reason` and the caps — defaults 2 a day and 20.00 USD a month, changed by owners and admins in Settings › API & webhooks). The purchase WAITS IN APPROVALS (202, `approval_key`) until a person approves it — in the app, or with approvals:decide + numbers:buy — and is bought at that moment through the app's own purchase, every check run again (the number still on sale and its price, the caps, the country's rules and business verification, the role, the outreach pause). An owner can switch on \"API may buy numbers without approval\"; then it's bought at once (201, or 202 while the order settles). The same number asked for again while it waits answers the waiting request. 409 with `reason` number_taken / price_unconfirmed / verification_required / purchase_failed; nothing is ever charged on a refusal. Releasing a number is done in the app only. `dry_run=true` checks everything and buys nothing. Fires number.purchased.\n\nRequires the `numbers:buy` scope (reaches people, spends or publishes).",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "numbers:buy"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "number": {
                    "type": "string",
                    "pattern": "^\\+\\d{7,16}$",
                    "description": "E.164, from GET /phone-numbers/available."
                  },
                  "country": {
                    "type": "string",
                    "pattern": "^[A-Za-z]{2}$"
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "local",
                      "mobile",
                      "tollfree"
                    ]
                  },
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  }
                },
                "required": [
                  "number",
                  "country",
                  "type"
                ],
                "additionalProperties": false
              },
              "example": {
                "number": "+46812345679",
                "country": "SE",
                "type": "local",
                "label": "Stockholm sales"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Buy a phone number",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "number_purchase"
                    },
                    "number": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "awaiting_approval",
                        "bought",
                        "pending",
                        "would_buy",
                        "would_wait"
                      ],
                      "description": "`awaiting_approval` = waiting in Approvals (`approval_key`); `bought` = yours now (`phone_number`); `pending` = the order is still settling; `would_buy` / `would_wait` = a dry run."
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "approval_key": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "phone_number": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            "object": {
                              "type": "string",
                              "const": "phone_number"
                            },
                            "number": {
                              "type": "string",
                              "description": "E.164."
                            },
                            "label": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "country": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "status": {
                              "type": "string",
                              "description": "`active`, or `pending` while a purchase settles."
                            },
                            "source": {
                              "type": "string",
                              "enum": [
                                "bought",
                                "connected"
                              ],
                              "description": "`bought` through NorReach, or `connected` from an account the workspace already had (voice only)."
                            },
                            "capabilities": {
                              "type": "object",
                              "properties": {
                                "voice": {
                                  "type": "boolean"
                                },
                                "sms": {
                                  "type": "boolean"
                                },
                                "mms": {
                                  "type": "boolean"
                                }
                              },
                              "required": [
                                "voice",
                                "sms",
                                "mms"
                              ],
                              "additionalProperties": false
                            },
                            "can_text": {
                              "type": "boolean",
                              "description": "Can send texts from NorReach (a bought number with SMS)."
                            },
                            "ai_calling": {
                              "type": "boolean",
                              "description": "Connected to AI calling."
                            },
                            "inbound_mode": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "enum": [
                                    "ai",
                                    "menu"
                                  ]
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Who answers incoming calls: `ai` = the AI agent, `menu` = the call menu (see GET /inbound-routing). Null for numbers that can't be switched."
                            },
                            "created_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "id",
                            "object",
                            "number",
                            "label",
                            "country",
                            "status",
                            "source",
                            "capabilities",
                            "can_text",
                            "ai_calling",
                            "inbound_mode",
                            "created_at"
                          ],
                          "additionalProperties": false,
                          "description": "One of the workspace's phone numbers."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "monthly_price": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "amount_minor": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "currency": {
                              "type": "string",
                              "minLength": 3,
                              "maxLength": 3
                            }
                          },
                          "required": [
                            "amount_minor",
                            "currency"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "caps": {
                      "type": "object",
                      "properties": {
                        "daily_limit": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "bought_today": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "monthly_ceiling": {
                          "type": "object",
                          "properties": {
                            "amount_minor": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "currency": {
                              "type": "string",
                              "minLength": 3,
                              "maxLength": 3
                            }
                          },
                          "required": [
                            "amount_minor",
                            "currency"
                          ],
                          "additionalProperties": false
                        },
                        "committed_this_month": {
                          "type": "object",
                          "properties": {
                            "amount_minor": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "currency": {
                              "type": "string",
                              "minLength": 3,
                              "maxLength": 3
                            }
                          },
                          "required": [
                            "amount_minor",
                            "currency"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "daily_limit",
                        "bought_today",
                        "monthly_ceiling",
                        "committed_this_month"
                      ],
                      "additionalProperties": false
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "number",
                    "status",
                    "dry_run",
                    "approval_key",
                    "phone_number",
                    "monthly_price",
                    "caps",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "A request to buy a number and where it stands."
                },
                "example": {
                  "object": "number_purchase",
                  "number": "+46812345679",
                  "status": "awaiting_approval",
                  "dry_run": false,
                  "approval_key": "number_buy:2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
                  "phone_number": null,
                  "monthly_price": {
                    "amount_minor": 300,
                    "currency": "USD"
                  },
                  "caps": {
                    "daily_limit": 2,
                    "bought_today": 0,
                    "monthly_ceiling": {
                      "amount_minor": 2000,
                      "currency": "USD"
                    },
                    "committed_this_month": {
                      "amount_minor": 0,
                      "currency": "USD"
                    }
                  },
                  "note": "Waiting in Approvals — nothing is bought until an owner or admin approves it."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again. · `number_cap_reached` — The workspace's limit for buying numbers through the API is reached.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "numbers:buy",
        "x-norreach-action": "numbers.buy",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/phone-numbers/{id}/inbound-mode": {
      "put": {
        "operationId": "set_number_inbound_mode",
        "summary": "Who answers a number: the AI agent or the call menu",
        "description": "Switches who answers one of the workspace's bought numbers — `ai` (the AI agent) or `menu` (the call menu: AI, your team, voicemail) — exactly as Settings › Inbound calls does: the number moves first, and the saved mode never claims what the number isn't. A number still settling or not switchable is 409 / 422. Owners, admins and managers. `dry_run=true` checks it and changes nothing.\n\nRequires the `calls:routing` scope (reaches people, spends or publishes).",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "calls:routing"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": [
                      "ai",
                      "menu"
                    ]
                  }
                },
                "required": [
                  "mode"
                ],
                "additionalProperties": false
              },
              "example": {
                "mode": "menu"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Who answers a number: the AI agent or the call menu",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "routing_number"
                    },
                    "number": {
                      "type": "string"
                    },
                    "label": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "inbound_mode": {
                      "type": "string",
                      "enum": [
                        "ai",
                        "menu"
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "number",
                    "label",
                    "inbound_mode"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "object": "routing_number",
                  "number": "+46812345678",
                  "label": "Stockholm office",
                  "inbound_mode": "menu"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "calls:routing",
        "x-norreach-action": "calls.routing",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/phone-numbers/available": {
      "get": {
        "operationId": "search_available_numbers",
        "summary": "Search numbers to buy",
        "description": "Numbers on sale now in a `country` (ISO alpha-2) of a `type` (`local`, `mobile`, `tollfree`), optionally containing some digits, in an area code, a city or (US / Canada) a state, and able to do `sms`, `voice` or `mms`. Up to 20 at a time, with the monthly price in minor units when the listing says. Some countries need a business verification first (GET /number-verifications/requirements). Buying is POST /phone-numbers.\n\nRequires the `numbers:read` scope.",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "numbers:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": true,
            "description": "ISO 3166-1 alpha-2, e.g. SE.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "default": "local",
              "type": "string",
              "enum": [
                "local",
                "mobile",
                "tollfree"
              ]
            }
          },
          {
            "name": "contains",
            "in": "query",
            "required": false,
            "description": "Digits the number should contain.",
            "schema": {
              "type": "string",
              "pattern": "^\\+?\\d{1,15}$"
            }
          },
          {
            "name": "area_code",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^\\d{1,6}$"
            }
          },
          {
            "name": "locality",
            "in": "query",
            "required": false,
            "description": "A city.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 60
            }
          },
          {
            "name": "region",
            "in": "query",
            "required": false,
            "description": "A state or province (US and Canada only).",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 60
            }
          },
          {
            "name": "sms",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "voice",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "mms",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search numbers to buy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "const": "available_number"
                          },
                          "number": {
                            "type": "string",
                            "description": "E.164 — pass it to POST /phone-numbers."
                          },
                          "country": {
                            "type": "string"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "local",
                              "mobile",
                              "tollfree"
                            ]
                          },
                          "locality": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "region": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "capabilities": {
                            "type": "object",
                            "properties": {
                              "voice": {
                                "type": "boolean"
                              },
                              "sms": {
                                "type": "boolean"
                              },
                              "mms": {
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "voice",
                              "sms",
                              "mms"
                            ],
                            "additionalProperties": false
                          },
                          "monthly_price": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "amount_minor": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "currency": {
                                    "type": "string",
                                    "minLength": 3,
                                    "maxLength": 3
                                  }
                                },
                                "required": [
                                  "amount_minor",
                                  "currency"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "What the number costs per month, when the listing says (rounded up to the currency's minor unit)."
                          },
                          "upfront_price": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "amount_minor": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "currency": {
                                    "type": "string",
                                    "minLength": 3,
                                    "maxLength": 3
                                  }
                                },
                                "required": [
                                  "amount_minor",
                                  "currency"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "A one-time cost at purchase, when there is one."
                          }
                        },
                        "required": [
                          "object",
                          "number",
                          "country",
                          "type",
                          "locality",
                          "region",
                          "capabilities",
                          "monthly_price",
                          "upfront_price"
                        ],
                        "additionalProperties": false,
                        "description": "A number that can be bought now."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "available_number",
                      "number": "+46812345679",
                      "country": "SE",
                      "type": "local",
                      "locality": "Stockholm",
                      "region": null,
                      "capabilities": {
                        "voice": true,
                        "sms": true,
                        "mms": false
                      },
                      "monthly_price": {
                        "amount_minor": 300,
                        "currency": "USD"
                      },
                      "upfront_price": null
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "numbers:read",
        "x-norreach-action": null,
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/plans": {
      "get": {
        "operationId": "list_plans",
        "summary": "List plans",
        "description": "The workspace's plans — each one Nora wrote from a brief — newest first, a page at a time, with their budget, autonomy, channels and how many cards are done or waiting for a person.\n\nRequires the `plans:read` scope.",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "generating",
                "review",
                "active",
                "paused",
                "completed",
                "failed"
              ]
            }
          },
          {
            "name": "goal_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "brand_awareness",
                "lead_gen",
                "nurture"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List plans",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "plan"
                          },
                          "name": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "generating",
                              "review",
                              "active",
                              "paused",
                              "completed",
                              "failed"
                            ]
                          },
                          "goal_type": {
                            "type": "string",
                            "enum": [
                              "brand_awareness",
                              "lead_gen",
                              "nurture"
                            ]
                          },
                          "playbook": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "brand_name": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "lead_status": {
                            "type": "string",
                            "enum": [
                              "have",
                              "need"
                            ],
                            "description": "have = the plan works on the workspace's own contacts; need = it finds people first."
                          },
                          "start_date": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "end_date": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "rationale": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Nora's reasoning for the plan's shape."
                          },
                          "kpis": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "budget": {
                            "type": "object",
                            "properties": {
                              "total": {
                                "type": "object",
                                "properties": {
                                  "amount_minor": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "currency": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "amount_minor",
                                  "currency"
                                ],
                                "additionalProperties": false,
                                "description": "Money in integer minor units (öre, cents)."
                              },
                              "per_week": {
                                "type": "object",
                                "properties": {
                                  "amount_minor": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "currency": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "amount_minor",
                                  "currency"
                                ],
                                "additionalProperties": false,
                                "description": "Money in integer minor units (öre, cents)."
                              },
                              "split": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "label": {
                                      "type": "string"
                                    },
                                    "amount": {
                                      "type": "object",
                                      "properties": {
                                        "amount_minor": {
                                          "type": "integer",
                                          "minimum": -9007199254740991,
                                          "maximum": 9007199254740991
                                        },
                                        "currency": {
                                          "type": "string"
                                        }
                                      },
                                      "required": [
                                        "amount_minor",
                                        "currency"
                                      ],
                                      "additionalProperties": false,
                                      "description": "Money in integer minor units (öre, cents)."
                                    },
                                    "cost_class": {
                                      "type": "string",
                                      "enum": [
                                        "free",
                                        "low",
                                        "high",
                                        "customer"
                                      ]
                                    },
                                    "note": {
                                      "type": "string"
                                    }
                                  },
                                  "required": [
                                    "label",
                                    "amount",
                                    "cost_class",
                                    "note"
                                  ],
                                  "additionalProperties": false
                                }
                              }
                            },
                            "required": [
                              "total",
                              "per_week",
                              "split"
                            ],
                            "additionalProperties": false
                          },
                          "autonomy": {
                            "type": "object",
                            "properties": {
                              "preset": {
                                "type": "string",
                                "enum": [
                                  "ask_everything",
                                  "auto_veto",
                                  "full_auto"
                                ],
                                "description": "ask_everything = every piece waits for a person; auto_veto = Nora goes ahead unless you stop her; full_auto = Nora runs it."
                              },
                              "policies": {
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {
                                  "type": "boolean"
                                },
                                "description": "Per-kind switches. quiet_hours and disclosure are always on."
                              }
                            },
                            "required": [
                              "preset",
                              "policies"
                            ],
                            "additionalProperties": false,
                            "description": "What Nora may do in this plan without asking."
                          },
                          "channels": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "channel": {
                                  "type": "string"
                                },
                                "role": {
                                  "type": "string",
                                  "enum": [
                                    "recommended",
                                    "optional"
                                  ]
                                },
                                "enabled": {
                                  "type": "boolean"
                                }
                              },
                              "required": [
                                "channel",
                                "role",
                                "enabled"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "cards": {
                            "type": "object",
                            "properties": {
                              "total": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "completed": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "awaiting_approval": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              }
                            },
                            "required": [
                              "total",
                              "completed",
                              "awaiting_approval"
                            ],
                            "additionalProperties": false
                          },
                          "generation": {
                            "type": "object",
                            "properties": {
                              "step": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "total": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "note": {
                                "type": "string",
                                "description": "What Nora is doing now (her own words)."
                              },
                              "done": {
                                "type": "boolean",
                                "description": "The plan is written (it is in review or later)."
                              },
                              "failed": {
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "step",
                              "total",
                              "note",
                              "done",
                              "failed"
                            ],
                            "additionalProperties": false
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "name",
                          "status",
                          "goal_type",
                          "playbook",
                          "brand_name",
                          "lead_status",
                          "start_date",
                          "end_date",
                          "rationale",
                          "kpis",
                          "budget",
                          "autonomy",
                          "channels",
                          "cards",
                          "generation",
                          "created_at"
                        ],
                        "additionalProperties": false,
                        "description": "A plan Nora wrote from a brief."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                      "object": "plan",
                      "name": "Example Care — 20 new nurse placements in Stockholm",
                      "status": "review",
                      "goal_type": "lead_gen",
                      "playbook": "Local services",
                      "brand_name": "Example Care",
                      "lead_status": "have",
                      "start_date": "2026-11-10",
                      "end_date": "2026-12-09",
                      "rationale": "Clinics decide in two weeks; the plan warms them with proof before it asks.",
                      "kpis": [
                        "Meetings booked",
                        "Cost per lead"
                      ],
                      "budget": {
                        "total": {
                          "amount_minor": 1500000,
                          "currency": "SEK"
                        },
                        "per_week": {
                          "amount_minor": 350000,
                          "currency": "SEK"
                        },
                        "split": [
                          {
                            "label": "Meta ads",
                            "amount": {
                              "amount_minor": 1000000,
                              "currency": "SEK"
                            },
                            "cost_class": "high",
                            "note": "Two weeks of lead ads"
                          }
                        ]
                      },
                      "autonomy": {
                        "preset": "auto_veto",
                        "policies": {
                          "quiet_hours": true,
                          "disclosure": true,
                          "ai_call": false
                        }
                      },
                      "channels": [
                        {
                          "channel": "email",
                          "role": "recommended",
                          "enabled": true
                        },
                        {
                          "channel": "paid_ad",
                          "role": "optional",
                          "enabled": true
                        }
                      ],
                      "cards": {
                        "total": 24,
                        "completed": 0,
                        "awaiting_approval": 3
                      },
                      "generation": {
                        "step": 7,
                        "total": 7,
                        "note": "done",
                        "done": true,
                        "failed": false
                      },
                      "created_at": "2026-11-04T09:12:33.120Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/plans/{id}": {
      "get": {
        "operationId": "get_plan",
        "summary": "One plan",
        "description": "A plan with its Overview numbers: how many leads stand at each stage of its arc, and how many people it found (and how many became contacts).\n\nRequires the `plans:read` scope.",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One plan",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "plan"
                    },
                    "name": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "generating",
                        "review",
                        "active",
                        "paused",
                        "completed",
                        "failed"
                      ]
                    },
                    "goal_type": {
                      "type": "string",
                      "enum": [
                        "brand_awareness",
                        "lead_gen",
                        "nurture"
                      ]
                    },
                    "playbook": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "brand_name": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lead_status": {
                      "type": "string",
                      "enum": [
                        "have",
                        "need"
                      ],
                      "description": "have = the plan works on the workspace's own contacts; need = it finds people first."
                    },
                    "start_date": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "end_date": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "rationale": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Nora's reasoning for the plan's shape."
                    },
                    "kpis": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "budget": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "object",
                          "properties": {
                            "amount_minor": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "currency": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "amount_minor",
                            "currency"
                          ],
                          "additionalProperties": false,
                          "description": "Money in integer minor units (öre, cents)."
                        },
                        "per_week": {
                          "type": "object",
                          "properties": {
                            "amount_minor": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "currency": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "amount_minor",
                            "currency"
                          ],
                          "additionalProperties": false,
                          "description": "Money in integer minor units (öre, cents)."
                        },
                        "split": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "label": {
                                "type": "string"
                              },
                              "amount": {
                                "type": "object",
                                "properties": {
                                  "amount_minor": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "currency": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "amount_minor",
                                  "currency"
                                ],
                                "additionalProperties": false,
                                "description": "Money in integer minor units (öre, cents)."
                              },
                              "cost_class": {
                                "type": "string",
                                "enum": [
                                  "free",
                                  "low",
                                  "high",
                                  "customer"
                                ]
                              },
                              "note": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "label",
                              "amount",
                              "cost_class",
                              "note"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "total",
                        "per_week",
                        "split"
                      ],
                      "additionalProperties": false
                    },
                    "autonomy": {
                      "type": "object",
                      "properties": {
                        "preset": {
                          "type": "string",
                          "enum": [
                            "ask_everything",
                            "auto_veto",
                            "full_auto"
                          ],
                          "description": "ask_everything = every piece waits for a person; auto_veto = Nora goes ahead unless you stop her; full_auto = Nora runs it."
                        },
                        "policies": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {
                            "type": "boolean"
                          },
                          "description": "Per-kind switches. quiet_hours and disclosure are always on."
                        }
                      },
                      "required": [
                        "preset",
                        "policies"
                      ],
                      "additionalProperties": false,
                      "description": "What Nora may do in this plan without asking."
                    },
                    "channels": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "channel": {
                            "type": "string"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "recommended",
                              "optional"
                            ]
                          },
                          "enabled": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "channel",
                          "role",
                          "enabled"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cards": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "completed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "awaiting_approval": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "total",
                        "completed",
                        "awaiting_approval"
                      ],
                      "additionalProperties": false
                    },
                    "generation": {
                      "type": "object",
                      "properties": {
                        "step": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "total": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "note": {
                          "type": "string",
                          "description": "What Nora is doing now (her own words)."
                        },
                        "done": {
                          "type": "boolean",
                          "description": "The plan is written (it is in review or later)."
                        },
                        "failed": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "step",
                        "total",
                        "note",
                        "done",
                        "failed"
                      ],
                      "additionalProperties": false
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "overview": {
                      "type": "object",
                      "properties": {
                        "arc": {
                          "anyOf": [
                            {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              }
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "How many leads stand at each stage of the plan's arc (null = couldn't be counted)."
                        },
                        "pool": {
                          "anyOf": [
                            {
                              "type": "object",
                              "properties": {
                                "total": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                "unlocked": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                "waiting": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                }
                              },
                              "required": [
                                "total",
                                "unlocked",
                                "waiting"
                              ],
                              "additionalProperties": false
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "People found for the plan: all of them, those who became contacts, those still waiting."
                        }
                      },
                      "required": [
                        "arc",
                        "pool"
                      ],
                      "additionalProperties": false,
                      "description": "The plan's Overview numbers."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "status",
                    "goal_type",
                    "playbook",
                    "brand_name",
                    "lead_status",
                    "start_date",
                    "end_date",
                    "rationale",
                    "kpis",
                    "budget",
                    "autonomy",
                    "channels",
                    "cards",
                    "generation",
                    "created_at",
                    "overview"
                  ],
                  "additionalProperties": false,
                  "description": "A plan with its Overview numbers."
                },
                "example": {
                  "id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                  "object": "plan",
                  "name": "Example Care — 20 new nurse placements in Stockholm",
                  "status": "review",
                  "goal_type": "lead_gen",
                  "playbook": "Local services",
                  "brand_name": "Example Care",
                  "lead_status": "have",
                  "start_date": "2026-11-10",
                  "end_date": "2026-12-09",
                  "rationale": "Clinics decide in two weeks; the plan warms them with proof before it asks.",
                  "kpis": [
                    "Meetings booked",
                    "Cost per lead"
                  ],
                  "budget": {
                    "total": {
                      "amount_minor": 1500000,
                      "currency": "SEK"
                    },
                    "per_week": {
                      "amount_minor": 350000,
                      "currency": "SEK"
                    },
                    "split": [
                      {
                        "label": "Meta ads",
                        "amount": {
                          "amount_minor": 1000000,
                          "currency": "SEK"
                        },
                        "cost_class": "high",
                        "note": "Two weeks of lead ads"
                      }
                    ]
                  },
                  "autonomy": {
                    "preset": "auto_veto",
                    "policies": {
                      "quiet_hours": true,
                      "disclosure": true,
                      "ai_call": false
                    }
                  },
                  "channels": [
                    {
                      "channel": "email",
                      "role": "recommended",
                      "enabled": true
                    },
                    {
                      "channel": "paid_ad",
                      "role": "optional",
                      "enabled": true
                    }
                  ],
                  "cards": {
                    "total": 24,
                    "completed": 0,
                    "awaiting_approval": 3
                  },
                  "generation": {
                    "step": 7,
                    "total": 7,
                    "note": "done",
                    "done": true,
                    "failed": false
                  },
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "overview": {
                    "arc": {
                      "curiosity": 40,
                      "awareness": 22,
                      "consideration": 9,
                      "proof": 4,
                      "offer": 2,
                      "urgency": 0,
                      "decision": 1
                    },
                    "pool": {
                      "total": 120,
                      "unlocked": 30,
                      "waiting": 90
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/plans/{id}/activate": {
      "post": {
        "operationId": "activate_plan",
        "summary": "Start a plan",
        "description": "Starts a plan in review (or a paused one) — its outreach, posts and ad launch drafts are wired up and its contacts enrolled, the same compile-then-write as the app's Start (a plan that can't be wired whole changes nothing, 409). Ad launches are created as drafts: money moves only once a launch is published. Starting a live plan again picks up newly connected channels (`recheck`). Waits while outreach is paused (409 outreach_paused). `dry_run=true` checks it and changes nothing.\n\nRequires the `plans:approve` scope (reaches people, spends or publishes).",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:approve"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Start a plan",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "plan_action"
                    },
                    "plan_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "activate",
                        "pause",
                        "apply_replan"
                      ]
                    },
                    "from": {
                      "type": "string",
                      "enum": [
                        "generating",
                        "review",
                        "active",
                        "paused",
                        "completed",
                        "failed"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "generating",
                        "review",
                        "active",
                        "paused",
                        "completed",
                        "failed"
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "recheck": {
                      "type": "boolean",
                      "description": "activate: a live plan was looked at again (newly connected channels picked up)."
                    },
                    "compiled": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "activate: how many cards this pass wired up."
                    },
                    "applied": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "apply_replan: how many changes landed."
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "object",
                    "plan_id",
                    "action",
                    "from",
                    "status",
                    "changed",
                    "dry_run",
                    "recheck",
                    "compiled",
                    "applied",
                    "warnings",
                    "notes"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "plan_action",
                  "plan_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                  "action": "activate",
                  "from": "review",
                  "status": "active",
                  "changed": true,
                  "dry_run": false,
                  "recheck": false,
                  "compiled": 24,
                  "applied": null,
                  "warnings": [],
                  "notes": [
                    "Enrolled 120 contacts from your lists."
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:approve",
        "x-norreach-action": "plan.approve",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/plans/{id}/autonomy": {
      "put": {
        "operationId": "set_plan_autonomy",
        "summary": "Set what Nora may do without asking",
        "description": "Sets the plan's autonomy: `preset` (ask_everything, auto_veto, full_auto) and optionally the per-kind `policies` (omitted = kept as they are). Quiet hours and AI-call disclosure stay on whatever is sent. Not while Nora is still writing the plan, nor on a finished or failed one (409).\n\nRequires the `nora:autonomy` scope.",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "nora:autonomy"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "preset": {
                    "type": "string",
                    "enum": [
                      "ask_everything",
                      "auto_veto",
                      "full_auto"
                    ]
                  },
                  "policies": {
                    "description": "Per-kind switches (quiet_hours and disclosure stay on whatever is sent).",
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[a-z][a-z_]{0,39}$"
                    },
                    "additionalProperties": {
                      "type": "boolean"
                    }
                  }
                },
                "required": [
                  "preset"
                ],
                "additionalProperties": false
              },
              "example": {
                "preset": "ask_everything"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Set what Nora may do without asking",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "plan_autonomy"
                    },
                    "plan_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "preset": {
                      "type": "string",
                      "enum": [
                        "ask_everything",
                        "auto_veto",
                        "full_auto"
                      ],
                      "description": "ask_everything = every piece waits for a person; auto_veto = Nora goes ahead unless you stop her; full_auto = Nora runs it."
                    },
                    "policies": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": "boolean"
                      },
                      "description": "Per-kind switches. quiet_hours and disclosure are always on."
                    }
                  },
                  "required": [
                    "object",
                    "plan_id",
                    "preset",
                    "policies"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "plan_autonomy",
                  "plan_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                  "preset": "ask_everything",
                  "policies": {
                    "quiet_hours": true,
                    "disclosure": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "nora:autonomy",
        "x-norreach-action": "nora.autonomy",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/plans/{id}/cards": {
      "get": {
        "operationId": "list_plan_cards",
        "summary": "A plan's cards",
        "description": "Every card of a plan in calendar order — one touch on one day, with its words, why it is there, its state and what holds it. Narrow it with `state` (awaiting_approval lists what waits for a person).\n\nRequires the `plans:read` scope.",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "queued",
                "awaiting_approval",
                "running",
                "completed",
                "skipped",
                "failed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A plan's cards",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "plan_card"
                          },
                          "plan_id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "date": {
                            "type": "string"
                          },
                          "time_label": {
                            "type": "string"
                          },
                          "scheduled_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "channel": {
                            "type": "string"
                          },
                          "arc_stage": {
                            "type": "string",
                            "enum": [
                              "curiosity",
                              "awareness",
                              "consideration",
                              "proof",
                              "offer",
                              "urgency",
                              "decision"
                            ]
                          },
                          "title": {
                            "type": "string"
                          },
                          "what": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {},
                            "description": "The card's words, by kind: email (subject, body), message (text), post (caption), call (opening), ad (primary …)."
                          },
                          "why": {
                            "type": "string"
                          },
                          "chain": {
                            "type": "string"
                          },
                          "state": {
                            "type": "string",
                            "enum": [
                              "queued",
                              "awaiting_approval",
                              "running",
                              "completed",
                              "skipped",
                              "failed"
                            ]
                          },
                          "conditional": {
                            "type": "boolean",
                            "description": "Fires on the lead's own behaviour rather than at a set time."
                          },
                          "cost_class": {
                            "type": "string",
                            "enum": [
                              "free",
                              "low",
                              "high",
                              "customer"
                            ]
                          },
                          "approved_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "hold": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "policy",
                                  "claim",
                                  "state"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Why it waits: policy (your plan's settings), claim (a claim needs checking — decide it in the app), state (the lead's own state)."
                          },
                          "claims": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "claim": {
                                  "type": "string"
                                },
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "flagged",
                                    "sourced"
                                  ]
                                },
                                "source": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                }
                              },
                              "required": [
                                "claim",
                                "status",
                                "source"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "outcome": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "note": {
                                    "type": "string"
                                  },
                                  "metrics": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "label": {
                                          "type": "string"
                                        },
                                        "value": {
                                          "type": "string"
                                        }
                                      },
                                      "required": [
                                        "label",
                                        "value"
                                      ],
                                      "additionalProperties": false
                                    }
                                  }
                                },
                                "required": [
                                  "note",
                                  "metrics"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "plan_id",
                          "date",
                          "time_label",
                          "scheduled_at",
                          "channel",
                          "arc_stage",
                          "title",
                          "what",
                          "why",
                          "chain",
                          "state",
                          "conditional",
                          "cost_class",
                          "approved_at",
                          "hold",
                          "claims",
                          "outcome"
                        ],
                        "additionalProperties": false,
                        "description": "One card of a plan — one touch on one day."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
                      "object": "plan_card",
                      "plan_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                      "date": "2026-11-12",
                      "time_label": "09:30",
                      "scheduled_at": null,
                      "channel": "email",
                      "arc_stage": "awareness",
                      "title": "Intro to clinic managers",
                      "what": {
                        "kind": "email",
                        "subject": "Nurses for the winter",
                        "body": "Hi {{first_name}}, …"
                      },
                      "why": "Clinic managers plan staffing a month ahead.",
                      "chain": "Opens feed the follow-up on day 4.",
                      "state": "awaiting_approval",
                      "conditional": false,
                      "cost_class": "free",
                      "approved_at": null,
                      "hold": "policy",
                      "claims": [],
                      "outcome": null
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/plans/{id}/generation": {
      "get": {
        "operationId": "get_plan_generation",
        "summary": "How far Nora is with a plan",
        "description": "Nora's progress writing the plan (step of total, her note), and — after POST /plans/{id}/replan — the change asked for and her proposal once it is written.\n\nRequires the `plans:read` scope.",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "How far Nora is with a plan",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "plan_generation"
                    },
                    "plan_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "generating",
                        "review",
                        "active",
                        "paused",
                        "completed",
                        "failed"
                      ]
                    },
                    "step": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "total": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "note": {
                      "type": "string"
                    },
                    "done": {
                      "type": "boolean"
                    },
                    "failed": {
                      "type": "boolean"
                    },
                    "error": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Why the last run stopped, for a person."
                    },
                    "replan": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "request": {
                              "type": "string"
                            },
                            "proposal": {
                              "anyOf": [
                                {
                                  "type": "object",
                                  "properties": {
                                    "summary": {
                                      "type": "string"
                                    },
                                    "items": {
                                      "type": "array",
                                      "items": {
                                        "type": "object",
                                        "properties": {
                                          "kind": {
                                            "type": "string",
                                            "enum": [
                                              "add",
                                              "remove",
                                              "move",
                                              "rebudget",
                                              "keep",
                                              "retime"
                                            ]
                                          },
                                          "text": {
                                            "type": "string"
                                          },
                                          "card_id": {
                                            "anyOf": [
                                              {
                                                "type": "string",
                                                "format": "uuid",
                                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                                "description": "An id (UUID)."
                                              },
                                              {
                                                "type": "null"
                                              }
                                            ]
                                          },
                                          "date": {
                                            "anyOf": [
                                              {
                                                "type": "string"
                                              },
                                              {
                                                "type": "null"
                                              }
                                            ]
                                          },
                                          "time_label": {
                                            "anyOf": [
                                              {
                                                "type": "string"
                                              },
                                              {
                                                "type": "null"
                                              }
                                            ]
                                          },
                                          "new_time": {
                                            "anyOf": [
                                              {
                                                "type": "string"
                                              },
                                              {
                                                "type": "null"
                                              }
                                            ]
                                          }
                                        },
                                        "required": [
                                          "kind",
                                          "text",
                                          "card_id",
                                          "date",
                                          "time_label",
                                          "new_time"
                                        ],
                                        "additionalProperties": false
                                      }
                                    },
                                    "unchanged_note": {
                                      "anyOf": [
                                        {
                                          "type": "string"
                                        },
                                        {
                                          "type": "null"
                                        }
                                      ]
                                    }
                                  },
                                  "required": [
                                    "summary",
                                    "items",
                                    "unchanged_note"
                                  ],
                                  "additionalProperties": false,
                                  "description": "The change Nora proposes — apply it with POST /plans/{id}/replan/apply."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "request",
                            "proposal"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The last change asked for, and Nora's proposal once it is written."
                    }
                  },
                  "required": [
                    "object",
                    "plan_id",
                    "status",
                    "step",
                    "total",
                    "note",
                    "done",
                    "failed",
                    "error",
                    "replan"
                  ],
                  "additionalProperties": false,
                  "description": "How far Nora is with writing (or re-planning) a plan."
                },
                "example": {
                  "object": "plan_generation",
                  "plan_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                  "status": "generating",
                  "step": 3,
                  "total": 7,
                  "note": "Writing the cards",
                  "done": false,
                  "failed": false,
                  "error": null,
                  "replan": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/plans/{id}/pause": {
      "post": {
        "operationId": "pause_plan",
        "summary": "Pause a plan",
        "description": "Pauses a running plan: its outreach sequence holds every contact where they stand. Posts already on the social calendar stay there (the answer says so). Pausing a paused plan changes nothing.\n\nRequires the `plans:approve` scope (reaches people, spends or publishes).",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:approve"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pause a plan",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "plan_action"
                    },
                    "plan_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "activate",
                        "pause",
                        "apply_replan"
                      ]
                    },
                    "from": {
                      "type": "string",
                      "enum": [
                        "generating",
                        "review",
                        "active",
                        "paused",
                        "completed",
                        "failed"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "generating",
                        "review",
                        "active",
                        "paused",
                        "completed",
                        "failed"
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "recheck": {
                      "type": "boolean",
                      "description": "activate: a live plan was looked at again (newly connected channels picked up)."
                    },
                    "compiled": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "activate: how many cards this pass wired up."
                    },
                    "applied": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "apply_replan: how many changes landed."
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "object",
                    "plan_id",
                    "action",
                    "from",
                    "status",
                    "changed",
                    "dry_run",
                    "recheck",
                    "compiled",
                    "applied",
                    "warnings",
                    "notes"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "plan_action",
                  "plan_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                  "action": "pause",
                  "from": "active",
                  "status": "paused",
                  "changed": true,
                  "dry_run": false,
                  "recheck": false,
                  "compiled": null,
                  "applied": null,
                  "warnings": [
                    "The outreach sequence is paused — contacts stay exactly where they are in it."
                  ],
                  "notes": []
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:approve",
        "x-norreach-action": "plan.approve",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/plans/{id}/replan": {
      "post": {
        "operationId": "replan_plan",
        "summary": "Ask Nora to change a plan",
        "description": "Tells Nora what to change, in words (and optionally a new ad budget, `budget_minor`, in the plan's currency). She writes a proposal — nothing changes until it is applied with POST /plans/{id}/replan/apply. Answers 202 with a `plan.replan` job whose `result.proposal` is the proposal once written. One change at a time: while one is still being worked out → 409.\n\nRequires the `plans:write` scope.",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "request": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  },
                  "budget_minor": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000000000
                  }
                },
                "required": [
                  "request"
                ],
                "additionalProperties": false
              },
              "example": {
                "request": "Fewer posts, more follow-up emails in week two."
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Ask Nora to change a plan",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "job"
                    },
                    "type": {
                      "type": "string",
                      "description": "What the job does (e.g. contacts.import)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "running",
                        "succeeded",
                        "failed"
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "finished_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "result": {
                      "anyOf": [
                        {},
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The job's answer once it succeeded."
                    },
                    "error": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "description": "A URL identifying the problem type."
                            },
                            "title": {
                              "type": "string",
                              "description": "A short, human summary (follows Accept-Language)."
                            },
                            "status": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "The HTTP status."
                            },
                            "code": {
                              "type": "string",
                              "enum": [
                                "bad_request",
                                "unknown_field",
                                "invalid_cursor",
                                "idempotency_key_required",
                                "unauthorized",
                                "key_revoked",
                                "key_expired",
                                "legacy_key",
                                "test_keys_not_available",
                                "key_owner_inactive",
                                "insufficient_scope",
                                "role_forbidden",
                                "ip_not_allowed",
                                "workspace_suspended",
                                "feature_not_enabled",
                                "key_suspended",
                                "member_locked",
                                "not_found",
                                "method_not_allowed",
                                "conflict",
                                "outreach_paused",
                                "already_decided",
                                "idempotency_in_progress",
                                "no_sender",
                                "insufficient_credits",
                                "too_large",
                                "validation_failed",
                                "send_blocked",
                                "publish_blocked",
                                "ad_publish_blocked",
                                "ad_switch_blocked",
                                "ad_network_unsupported",
                                "post_schedule_blocked",
                                "ads_by_plan",
                                "idempotency_mismatch",
                                "rate_limited",
                                "send_cap_reached",
                                "number_cap_reached",
                                "server_error",
                                "unavailable"
                              ],
                              "description": "Stable machine-readable code."
                            },
                            "detail": {
                              "description": "What happened, for a person (follows Accept-Language).",
                              "type": "string"
                            },
                            "instance": {
                              "description": "The request id.",
                              "type": "string"
                            },
                            "errors": {
                              "description": "Field-level problems (validation_failed, unknown_field).",
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "path": {
                                    "type": "string"
                                  },
                                  "code": {
                                    "type": "string"
                                  },
                                  "message": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "path",
                                  "code",
                                  "message"
                                ],
                                "additionalProperties": false
                              }
                            },
                            "docs": {
                              "type": "string",
                              "description": "Where this code is explained."
                            }
                          },
                          "required": [
                            "type",
                            "title",
                            "status",
                            "code",
                            "docs"
                          ],
                          "additionalProperties": {},
                          "description": "RFC 9457 problem details."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Why it failed."
                    },
                    "resource": {
                      "description": "What the job works on — GET it for the full object.",
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "object": {
                              "type": "string",
                              "description": "What kind of thing (e.g. plan)."
                            },
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            }
                          },
                          "required": [
                            "object",
                            "id"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "type",
                    "status",
                    "created_at",
                    "finished_at",
                    "result",
                    "error"
                  ],
                  "additionalProperties": false,
                  "description": "A long-running job."
                },
                "example": {
                  "id": "2f9c1a7e-5b3d-4e8f-9a1b-6c7d8e9f0a1b",
                  "object": "job",
                  "type": "plan.replan",
                  "status": "queued",
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "finished_at": null,
                  "result": null,
                  "error": null,
                  "resource": {
                    "object": "plan",
                    "id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:write",
        "x-norreach-action": "plan.edit",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/plans/{id}/replan/apply": {
      "post": {
        "operationId": "apply_plan_replan",
        "summary": "Apply Nora's proposal",
        "description": "Applies the proposal Nora wrote after POST /plans/{id}/replan — all of it or none of it (a proposal with a change the plan can't take changes nothing, 409). A removed card is skipped, not deleted. Cards added to a live plan are wired up the next time it is activated.\n\nRequires the `plans:write` scope.",
        "tags": [
          "Plans"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "plans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Apply Nora's proposal",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "plan_action"
                    },
                    "plan_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "activate",
                        "pause",
                        "apply_replan"
                      ]
                    },
                    "from": {
                      "type": "string",
                      "enum": [
                        "generating",
                        "review",
                        "active",
                        "paused",
                        "completed",
                        "failed"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "generating",
                        "review",
                        "active",
                        "paused",
                        "completed",
                        "failed"
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "recheck": {
                      "type": "boolean",
                      "description": "activate: a live plan was looked at again (newly connected channels picked up)."
                    },
                    "compiled": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "activate: how many cards this pass wired up."
                    },
                    "applied": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "apply_replan: how many changes landed."
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "object",
                    "plan_id",
                    "action",
                    "from",
                    "status",
                    "changed",
                    "dry_run",
                    "recheck",
                    "compiled",
                    "applied",
                    "warnings",
                    "notes"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "plan_action",
                  "plan_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
                  "action": "apply_replan",
                  "from": "active",
                  "status": "active",
                  "changed": true,
                  "dry_run": false,
                  "recheck": false,
                  "compiled": null,
                  "applied": 3,
                  "warnings": [],
                  "notes": []
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "plans:write",
        "x-norreach-action": "plan.edit",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/senders": {
      "get": {
        "operationId": "list_senders",
        "summary": "Connected senders",
        "description": "What the workspace can send from, per channel — email inboxes, verified domain senders, phone numbers (texting, AI calling, or voice only), WhatsApp numbers and LinkedIn seats — read exactly the way a campaign launch checks them, so `channels.<channel>.ready: false` is the reason a launch answers 409 no_sender. Connecting senders happens in the app.\n\nRequires the `workspace:read` scope.",
        "tags": [
          "Workspace"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "workspace:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Connected senders",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "senders"
                    },
                    "channels": {
                      "type": "object",
                      "properties": {
                        "email": {
                          "type": "object",
                          "properties": {
                            "ready": {
                              "type": "boolean"
                            },
                            "count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            }
                          },
                          "required": [
                            "ready",
                            "count"
                          ],
                          "additionalProperties": false
                        },
                        "sms": {
                          "type": "object",
                          "properties": {
                            "ready": {
                              "type": "boolean"
                            },
                            "count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            }
                          },
                          "required": [
                            "ready",
                            "count"
                          ],
                          "additionalProperties": false
                        },
                        "call": {
                          "type": "object",
                          "properties": {
                            "ready": {
                              "type": "boolean"
                            },
                            "count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            }
                          },
                          "required": [
                            "ready",
                            "count"
                          ],
                          "additionalProperties": false
                        },
                        "whatsapp": {
                          "type": "object",
                          "properties": {
                            "ready": {
                              "type": "boolean"
                            },
                            "count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            }
                          },
                          "required": [
                            "ready",
                            "count"
                          ],
                          "additionalProperties": false
                        },
                        "linkedin": {
                          "type": "object",
                          "properties": {
                            "ready": {
                              "type": "boolean"
                            },
                            "count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            }
                          },
                          "required": [
                            "ready",
                            "count"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "email",
                        "sms",
                        "call",
                        "whatsapp",
                        "linkedin"
                      ],
                      "additionalProperties": false
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "const": "sender"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "email_inbox",
                              "domain_sender",
                              "phone_number",
                              "whatsapp_number",
                              "linkedin_seat"
                            ]
                          },
                          "label": {
                            "type": "string",
                            "description": "\"email inbox\", \"domain sender\", \"phone number\", \"WhatsApp number\" or \"LinkedIn seat\"."
                          },
                          "address": {
                            "type": "string",
                            "description": "The address, domain, number or seat name."
                          },
                          "name": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "What you called it, when you named it."
                          },
                          "channels": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "email",
                                "sms",
                                "call",
                                "whatsapp",
                                "linkedin"
                              ]
                            },
                            "description": "What it can send on now."
                          },
                          "status": {
                            "type": "string",
                            "description": "connected / verified, or the seat's state (e.g. needs_attention)."
                          },
                          "verified": {
                            "type": "boolean"
                          },
                          "voice_only": {
                            "type": "boolean",
                            "description": "A number that can call but not text."
                          },
                          "ai_calling": {
                            "anyOf": [
                              {
                                "type": "boolean"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Numbers: connected to AI calling."
                          },
                          "country": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "object",
                          "kind",
                          "label",
                          "address",
                          "name",
                          "channels",
                          "status",
                          "verified",
                          "voice_only",
                          "ai_calling",
                          "country"
                        ],
                        "additionalProperties": false,
                        "description": "One connected sending identity."
                      }
                    },
                    "complete": {
                      "type": "boolean",
                      "description": "false: a part couldn't be read just now — what's missing may be connected."
                    }
                  },
                  "required": [
                    "object",
                    "channels",
                    "data",
                    "complete"
                  ],
                  "additionalProperties": false,
                  "description": "The workspace's connected sending identities, per channel — what campaigns can send from."
                },
                "example": {
                  "object": "senders",
                  "channels": {
                    "email": {
                      "ready": true,
                      "count": 1
                    },
                    "sms": {
                      "ready": false,
                      "count": 0
                    },
                    "call": {
                      "ready": true,
                      "count": 1
                    },
                    "whatsapp": {
                      "ready": false,
                      "count": 0
                    },
                    "linkedin": {
                      "ready": false,
                      "count": 0
                    }
                  },
                  "data": [
                    {
                      "object": "sender",
                      "kind": "email_inbox",
                      "label": "email inbox",
                      "address": "sales@acme.example",
                      "name": null,
                      "channels": [
                        "email"
                      ],
                      "status": "connected",
                      "verified": true,
                      "voice_only": false,
                      "ai_calling": null,
                      "country": null
                    },
                    {
                      "object": "sender",
                      "kind": "phone_number",
                      "label": "phone number",
                      "address": "+46812345678",
                      "name": "Stockholm office",
                      "channels": [
                        "call"
                      ],
                      "status": "connected",
                      "verified": true,
                      "voice_only": true,
                      "ai_calling": true,
                      "country": "SE"
                    }
                  ],
                  "complete": true
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "workspace:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/sequence-templates": {
      "get": {
        "operationId": "list_sequence_templates",
        "summary": "List sequence templates",
        "description": "Ready-made sequences: the ones NorReach ships (`built_in`) and the ones this workspace saved. Use their steps and rules to create a campaign.\n\nRequires the `campaigns:read` scope.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "campaigns:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List sequence templates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "sequence_template"
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "steps": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {}
                            }
                          },
                          "rules": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {}
                            }
                          },
                          "built_in": {
                            "type": "boolean",
                            "description": "Shipped with NorReach (else saved by this workspace)."
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "name",
                          "description",
                          "steps",
                          "rules",
                          "built_in",
                          "created_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "9f0a1b2c-3d4e-4f5a-8b6c-7d8e9f0a1b2c",
                      "object": "sequence_template",
                      "name": "Three-touch email",
                      "description": "Intro, follow-up, break-up.",
                      "steps": [
                        {
                          "channel": "email",
                          "wait_hours": 0,
                          "template": "Subject: Nurses for the summer\n\nHi {{first_name}}, …"
                        }
                      ],
                      "rules": [],
                      "built_in": true,
                      "created_at": "2026-06-01T00:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "campaigns:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/sites": {
      "get": {
        "operationId": "list_sites",
        "summary": "List sites",
        "description": "The workspace's landing-page sites: their address, language, company details, look and custom domains.\n\nRequires the `pages:read` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List sites",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "site"
                          },
                          "name": {
                            "type": "string"
                          },
                          "subdomain": {
                            "type": "string"
                          },
                          "primary_host": {
                            "type": "string",
                            "description": "Where the site's pages are served."
                          },
                          "default_language": {
                            "type": "string",
                            "enum": [
                              "en",
                              "sv"
                            ]
                          },
                          "status": {
                            "type": "string"
                          },
                          "legal": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {
                              "type": "string"
                            },
                            "description": "The company details every page shows."
                          },
                          "theme": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {}
                          },
                          "domains": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                  "description": "An id (UUID)."
                                },
                                "object": {
                                  "type": "string",
                                  "const": "domain"
                                },
                                "hostname": {
                                  "type": "string"
                                },
                                "status": {
                                  "type": "string",
                                  "description": "Where setting it up has got to (e.g. pending, active, misconfigured)."
                                },
                                "is_primary": {
                                  "type": "boolean"
                                },
                                "redirect_to": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "records": {
                                  "description": "The DNS records to set at your domain's provider."
                                },
                                "last_error": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "last_checked_at": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "description": "RFC 3339 UTC timestamp with milliseconds."
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                }
                              },
                              "required": [
                                "id",
                                "object",
                                "hostname",
                                "status",
                                "is_primary",
                                "redirect_to",
                                "records",
                                "last_error",
                                "last_checked_at"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "name",
                          "subdomain",
                          "primary_host",
                          "default_language",
                          "status",
                          "legal",
                          "theme",
                          "domains"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                      "object": "site",
                      "name": "Acme Staffing",
                      "subdomain": "acme",
                      "primary_host": "acme.norreach.page",
                      "default_language": "sv",
                      "status": "active",
                      "legal": {
                        "company_name": "Acme Staffing AB"
                      },
                      "theme": {},
                      "domains": []
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/sites/{id}": {
      "get": {
        "operationId": "get_site",
        "summary": "One site",
        "description": "A landing-page site with its company details, look and custom domains.\n\nRequires the `pages:read` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One site",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "site"
                    },
                    "name": {
                      "type": "string"
                    },
                    "subdomain": {
                      "type": "string"
                    },
                    "primary_host": {
                      "type": "string",
                      "description": "Where the site's pages are served."
                    },
                    "default_language": {
                      "type": "string",
                      "enum": [
                        "en",
                        "sv"
                      ]
                    },
                    "status": {
                      "type": "string"
                    },
                    "legal": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": "string"
                      },
                      "description": "The company details every page shows."
                    },
                    "theme": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {}
                    },
                    "domains": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "domain"
                          },
                          "hostname": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "description": "Where setting it up has got to (e.g. pending, active, misconfigured)."
                          },
                          "is_primary": {
                            "type": "boolean"
                          },
                          "redirect_to": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "records": {
                            "description": "The DNS records to set at your domain's provider."
                          },
                          "last_error": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "last_checked_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "hostname",
                          "status",
                          "is_primary",
                          "redirect_to",
                          "records",
                          "last_error",
                          "last_checked_at"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "subdomain",
                    "primary_host",
                    "default_language",
                    "status",
                    "legal",
                    "theme",
                    "domains"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                  "object": "site",
                  "name": "Acme Staffing",
                  "subdomain": "acme",
                  "primary_host": "acme.norreach.page",
                  "default_language": "sv",
                  "status": "active",
                  "legal": {
                    "company_name": "Acme Staffing AB"
                  },
                  "theme": {},
                  "domains": []
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_site",
        "summary": "Update a site",
        "description": "The company details every page shows (`legal`), the look (`theme`) and the default language. Ad pixels are chosen in the app (they need a connected ad account).\n\nRequires the `pages:write` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "legal": {
                    "type": "object",
                    "properties": {
                      "company_name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "org_number": {
                        "type": "string",
                        "maxLength": 40
                      },
                      "address": {
                        "type": "string",
                        "maxLength": 300
                      },
                      "email": {
                        "type": "string",
                        "maxLength": 254
                      },
                      "phone": {
                        "type": "string",
                        "maxLength": 40
                      },
                      "hours": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "privacy_url": {
                        "type": "string",
                        "maxLength": 500
                      },
                      "terms_url": {
                        "type": "string",
                        "maxLength": 500
                      }
                    },
                    "required": [
                      "company_name"
                    ],
                    "additionalProperties": false
                  },
                  "theme": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  },
                  "default_language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "sv"
                    ]
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "legal": {
                  "company_name": "Acme Staffing AB",
                  "email": "hello@acme.example"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Update a site",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "site"
                    },
                    "name": {
                      "type": "string"
                    },
                    "subdomain": {
                      "type": "string"
                    },
                    "primary_host": {
                      "type": "string",
                      "description": "Where the site's pages are served."
                    },
                    "default_language": {
                      "type": "string",
                      "enum": [
                        "en",
                        "sv"
                      ]
                    },
                    "status": {
                      "type": "string"
                    },
                    "legal": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": "string"
                      },
                      "description": "The company details every page shows."
                    },
                    "theme": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {}
                    },
                    "domains": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "domain"
                          },
                          "hostname": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "description": "Where setting it up has got to (e.g. pending, active, misconfigured)."
                          },
                          "is_primary": {
                            "type": "boolean"
                          },
                          "redirect_to": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "records": {
                            "description": "The DNS records to set at your domain's provider."
                          },
                          "last_error": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "last_checked_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "hostname",
                          "status",
                          "is_primary",
                          "redirect_to",
                          "records",
                          "last_error",
                          "last_checked_at"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "subdomain",
                    "primary_host",
                    "default_language",
                    "status",
                    "legal",
                    "theme",
                    "domains"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                  "object": "site",
                  "name": "Acme Staffing",
                  "subdomain": "acme",
                  "primary_host": "acme.norreach.page",
                  "default_language": "sv",
                  "status": "active",
                  "legal": {
                    "company_name": "Acme Staffing AB"
                  },
                  "theme": {},
                  "domains": []
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:write",
        "x-norreach-action": "pages.edit",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/sites/{id}/domains": {
      "get": {
        "operationId": "list_site_domains",
        "summary": "A site's custom domains",
        "description": "The site's own domains, with the DNS records to set and where each one has got to.\n\nRequires the `pages:read` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A site's custom domains",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "domain"
                          },
                          "hostname": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "description": "Where setting it up has got to (e.g. pending, active, misconfigured)."
                          },
                          "is_primary": {
                            "type": "boolean"
                          },
                          "redirect_to": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "records": {
                            "description": "The DNS records to set at your domain's provider."
                          },
                          "last_error": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "last_checked_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "hostname",
                          "status",
                          "is_primary",
                          "redirect_to",
                          "records",
                          "last_error",
                          "last_checked_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "9d0e1f2a-3b4c-4d5e-8f6a-7b8c9d0e1f2a",
                      "object": "domain",
                      "hostname": "go.acme.example",
                      "status": "pending",
                      "is_primary": false,
                      "redirect_to": null,
                      "records": [
                        {
                          "type": "CNAME",
                          "name": "go",
                          "value": "sites.norreach.page"
                        }
                      ],
                      "last_error": null,
                      "last_checked_at": null
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "add_site_domain",
        "summary": "Add a custom domain",
        "description": "Adds your own domain (e.g. go.example.com) to a site. The answer lists the DNS records to set at your domain's provider; then call verify.\n\nRequires the `pages:domains` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:domains"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "hostname": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 253
                  }
                },
                "required": [
                  "hostname"
                ],
                "additionalProperties": false
              },
              "example": {
                "hostname": "go.acme.example"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Add a custom domain",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "domain"
                          },
                          "hostname": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "description": "Where setting it up has got to (e.g. pending, active, misconfigured)."
                          },
                          "is_primary": {
                            "type": "boolean"
                          },
                          "redirect_to": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "records": {
                            "description": "The DNS records to set at your domain's provider."
                          },
                          "last_error": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "last_checked_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "hostname",
                          "status",
                          "is_primary",
                          "redirect_to",
                          "records",
                          "last_error",
                          "last_checked_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:domains",
        "x-norreach-action": "pages.domains",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/sites/{id}/domains/{domain_id}": {
      "delete": {
        "operationId": "remove_site_domain",
        "summary": "Remove a custom domain",
        "description": "Removes the domain from the site; pages go back to the free address. Send `hostname` to confirm when the domain is the main address or live ads point at it.\n\nRequires the `pages:domains` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:domains"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "domain_id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "hostname": {
                    "type": "string",
                    "maxLength": 253
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Remove a custom domain",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "domain"
                          },
                          "hostname": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "description": "Where setting it up has got to (e.g. pending, active, misconfigured)."
                          },
                          "is_primary": {
                            "type": "boolean"
                          },
                          "redirect_to": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "records": {
                            "description": "The DNS records to set at your domain's provider."
                          },
                          "last_error": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "last_checked_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "hostname",
                          "status",
                          "is_primary",
                          "redirect_to",
                          "records",
                          "last_error",
                          "last_checked_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:domains",
        "x-norreach-action": "pages.domains",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/sites/{id}/domains/{domain_id}/primary": {
      "post": {
        "operationId": "make_site_domain_primary",
        "summary": "Make a domain the main address",
        "description": "Serves the site's pages on this domain (the free address then forwards to it). The domain must be active.\n\nRequires the `pages:domains` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:domains"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "domain_id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Make a domain the main address",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "domain"
                          },
                          "hostname": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "description": "Where setting it up has got to (e.g. pending, active, misconfigured)."
                          },
                          "is_primary": {
                            "type": "boolean"
                          },
                          "redirect_to": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "records": {
                            "description": "The DNS records to set at your domain's provider."
                          },
                          "last_error": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "last_checked_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "hostname",
                          "status",
                          "is_primary",
                          "redirect_to",
                          "records",
                          "last_error",
                          "last_checked_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:domains",
        "x-norreach-action": "pages.domains",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/sites/{id}/domains/{domain_id}/verify": {
      "post": {
        "operationId": "verify_site_domain",
        "summary": "Check a custom domain",
        "description": "Checks the domain's DNS now and moves it along when the records are right.\n\nRequires the `pages:domains` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:domains"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "domain_id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Check a custom domain",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "domain"
                          },
                          "hostname": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "description": "Where setting it up has got to (e.g. pending, active, misconfigured)."
                          },
                          "is_primary": {
                            "type": "boolean"
                          },
                          "redirect_to": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "records": {
                            "description": "The DNS records to set at your domain's provider."
                          },
                          "last_error": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "last_checked_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "hostname",
                          "status",
                          "is_primary",
                          "redirect_to",
                          "records",
                          "last_error",
                          "last_checked_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:domains",
        "x-norreach-action": "pages.domains",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/social/accounts": {
      "get": {
        "operationId": "list_social_accounts",
        "summary": "List connected social profiles",
        "description": "The social profiles connected to the workspace (LinkedIn, X, Instagram, Facebook, TikTok): network, display name, handle and whether it can post now (`needs_reconnect` = sign in again in the app). Posts go out through each network's connected profile. Connecting or removing a profile happens in the app — never through the API.\n\nRequires the `social:read` scope.",
        "tags": [
          "Social"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "social:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List connected social profiles",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "A stable id for this connected profile in NorReach."
                          },
                          "object": {
                            "type": "string",
                            "const": "social_account"
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "linkedin",
                              "x",
                              "instagram",
                              "facebook",
                              "tiktok"
                            ],
                            "description": "linkedin, x, instagram, facebook or tiktok."
                          },
                          "network_name": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string",
                            "description": "The profile's or page's display name."
                          },
                          "handle": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The public handle, when the network has one."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "needs_reconnect"
                            ],
                            "description": "`needs_reconnect`: the sign-in went stale — reconnect it in the app; scheduling to this network is refused until then."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "network",
                          "network_name",
                          "name",
                          "handle",
                          "status"
                        ],
                        "additionalProperties": false,
                        "description": "A social profile connected to the workspace. Posts go out through the connected profile of each network."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "8b9c0d1e-2f3a-8b4c-9d5e-6f7a8b9c0d1e",
                      "object": "social_account",
                      "network": "linkedin",
                      "network_name": "LinkedIn",
                      "name": "Example Care",
                      "handle": null,
                      "status": "active"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "social:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/social/posts": {
      "get": {
        "operationId": "list_social_posts",
        "summary": "List social posts",
        "description": "The workspace's social posts, newest first, each with its version per network (text, media, publish state). Filter by `status`, by `network` (posts with a version for it) and by when they are scheduled (`scheduled_from` / `scheduled_to`). Posts carry your own text, pictures and videos — there is no operation that writes posts with AI (Nora writes posts in a plan: POST /briefs).\n\nRequires the `social:read` scope.",
        "tags": [
          "Social"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "social:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "idea",
                "draft",
                "in_review",
                "scheduled",
                "publishing",
                "published",
                "failed"
              ]
            }
          },
          {
            "name": "network",
            "in": "query",
            "required": false,
            "description": "linkedin, x, instagram, facebook or tiktok.",
            "schema": {
              "type": "string",
              "enum": [
                "linkedin",
                "x",
                "instagram",
                "facebook",
                "tiktok"
              ]
            }
          },
          {
            "name": "scheduled_from",
            "in": "query",
            "required": false,
            "description": "Only posts scheduled at or after this time (RFC 3339).",
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "scheduled_to",
            "in": "query",
            "required": false,
            "description": "Only posts scheduled at or before this time (RFC 3339).",
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List social posts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "social_post"
                          },
                          "title": {
                            "type": "string",
                            "description": "The post's name in the calendar (never published)."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "idea",
                              "draft",
                              "in_review",
                              "scheduled",
                              "publishing",
                              "published",
                              "failed"
                            ],
                            "description": "idea, draft, in_review, scheduled, publishing, published or failed."
                          },
                          "scheduled_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "When it goes out (scheduled posts)."
                          },
                          "timezone": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The IANA time zone it was scheduled in, for display."
                          },
                          "labels": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "notes": {
                            "type": "string",
                            "description": "Internal notes (never published)."
                          },
                          "networks": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "linkedin",
                                "x",
                                "instagram",
                                "facebook",
                                "tiktok"
                              ],
                              "description": "linkedin, x, instagram, facebook or tiktok."
                            }
                          },
                          "variants": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "network": {
                                  "type": "string",
                                  "enum": [
                                    "linkedin",
                                    "x",
                                    "instagram",
                                    "facebook",
                                    "tiktok"
                                  ],
                                  "description": "linkedin, x, instagram, facebook or tiktok."
                                },
                                "network_name": {
                                  "type": "string"
                                },
                                "content": {
                                  "type": "string",
                                  "description": "The text for this network."
                                },
                                "media_urls": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  },
                                  "description": "Pictures and videos, in order (public https addresses)."
                                },
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "pending",
                                    "publishing",
                                    "published",
                                    "failed"
                                  ],
                                  "description": "`pending` (not sent yet), `publishing`, `published` or `failed`."
                                },
                                "published_at": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "description": "RFC 3339 UTC timestamp with milliseconds."
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "problem": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "When this network's publish failed: a plain sentence (the details are in the app)."
                                }
                              },
                              "required": [
                                "network",
                                "network_name",
                                "content",
                                "media_urls",
                                "status",
                                "published_at",
                                "problem"
                              ],
                              "additionalProperties": false,
                              "description": "The post's version for one network."
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "updated_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "title",
                          "status",
                          "scheduled_at",
                          "timezone",
                          "labels",
                          "notes",
                          "networks",
                          "variants",
                          "created_at",
                          "updated_at"
                        ],
                        "additionalProperties": false,
                        "description": "A social post: your own text, pictures and videos, one version per network."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                      "object": "social_post",
                      "title": "Winter staffing",
                      "status": "scheduled",
                      "scheduled_at": "2026-11-12T08:30:00.000Z",
                      "timezone": "Europe/Stockholm",
                      "labels": [
                        "winter"
                      ],
                      "notes": "",
                      "networks": [
                        "linkedin",
                        "instagram"
                      ],
                      "variants": [
                        {
                          "network": "linkedin",
                          "network_name": "LinkedIn",
                          "content": "Clinics plan their winter staffing now. We place licensed nurses within 48 hours.",
                          "media_urls": [],
                          "status": "pending",
                          "published_at": null,
                          "problem": null
                        },
                        {
                          "network": "instagram",
                          "network_name": "Instagram",
                          "content": "Winter is coming — so are our nurses.",
                          "media_urls": [
                            "https://media.example.com/social-media/6a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d/2f3e4d5c-6b7a-4c8d-9e0f-1a2b3c4d5e6f.jpg"
                          ],
                          "status": "pending",
                          "published_at": null,
                          "problem": null
                        }
                      ],
                      "created_at": "2026-11-05T09:12:33.120Z",
                      "updated_at": "2026-11-05T09:20:01.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "social:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "create_social_post",
        "summary": "Create a social post",
        "description": "Creates a post (a draft by default) with your own text and media, one version per network — through the app's social calendar, exactly as the composer saves. Nothing goes out: schedule it with POST /social/posts/{id}/schedule. Media: public http(s) addresses, or upload a file first with POST /social/uploads; a file in another workspace's media is refused (422). Each network's character limit and Instagram's need for a picture are checked when scheduling. Posts carry your own text, pictures and videos — there is no operation that writes posts with AI (Nora writes posts in a plan: POST /briefs). Owners, admins and managers.\n\nRequires the `social:publish` scope (reaches people, spends or publishes).",
        "tags": [
          "Social"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "social:publish"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "The post's name in the calendar (never published)."
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "idea",
                      "draft",
                      "in_review"
                    ],
                    "description": "idea, draft (default) or in_review — scheduling has its own operation."
                  },
                  "labels": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 50
                    }
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 5000,
                    "description": "Internal notes (never published)."
                  },
                  "variants": {
                    "default": [],
                    "description": "One version per network, with your own text and media.",
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "network": {
                          "type": "string",
                          "enum": [
                            "linkedin",
                            "x",
                            "instagram",
                            "facebook",
                            "tiktok"
                          ],
                          "description": "linkedin, x, instagram, facebook or tiktok."
                        },
                        "content": {
                          "default": "",
                          "description": "The text for this network (each network's own limit is checked when scheduling: X 280, LinkedIn 3000, Instagram 2200, Facebook 5000, TikTok 2200).",
                          "type": "string",
                          "maxLength": 10000
                        },
                        "media_urls": {
                          "default": [],
                          "description": "Up to 10 pictures or videos. Instagram needs at least one to be scheduled.",
                          "maxItems": 10,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "maxLength": 2000,
                            "description": "A public http(s) address of a picture or video (e.g. a `media_url` from POST /social/uploads)."
                          }
                        }
                      },
                      "required": [
                        "network"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "title": "Winter staffing",
                "labels": [
                  "winter"
                ],
                "variants": [
                  {
                    "network": "linkedin",
                    "content": "Clinics plan their winter staffing now. We place licensed nurses within 48 hours."
                  },
                  {
                    "network": "instagram",
                    "content": "Winter is coming — so are our nurses.",
                    "media_urls": [
                      "https://media.example.com/social-media/6a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d/2f3e4d5c-6b7a-4c8d-9e0f-1a2b3c4d5e6f.jpg"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Create a social post",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "social_post"
                    },
                    "title": {
                      "type": "string",
                      "description": "The post's name in the calendar (never published)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "idea",
                        "draft",
                        "in_review",
                        "scheduled",
                        "publishing",
                        "published",
                        "failed"
                      ],
                      "description": "idea, draft, in_review, scheduled, publishing, published or failed."
                    },
                    "scheduled_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "When it goes out (scheduled posts)."
                    },
                    "timezone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The IANA time zone it was scheduled in, for display."
                    },
                    "labels": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "notes": {
                      "type": "string",
                      "description": "Internal notes (never published)."
                    },
                    "networks": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "linkedin",
                          "x",
                          "instagram",
                          "facebook",
                          "tiktok"
                        ],
                        "description": "linkedin, x, instagram, facebook or tiktok."
                      }
                    },
                    "variants": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "network": {
                            "type": "string",
                            "enum": [
                              "linkedin",
                              "x",
                              "instagram",
                              "facebook",
                              "tiktok"
                            ],
                            "description": "linkedin, x, instagram, facebook or tiktok."
                          },
                          "network_name": {
                            "type": "string"
                          },
                          "content": {
                            "type": "string",
                            "description": "The text for this network."
                          },
                          "media_urls": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Pictures and videos, in order (public https addresses)."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "publishing",
                              "published",
                              "failed"
                            ],
                            "description": "`pending` (not sent yet), `publishing`, `published` or `failed`."
                          },
                          "published_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "problem": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "When this network's publish failed: a plain sentence (the details are in the app)."
                          }
                        },
                        "required": [
                          "network",
                          "network_name",
                          "content",
                          "media_urls",
                          "status",
                          "published_at",
                          "problem"
                        ],
                        "additionalProperties": false,
                        "description": "The post's version for one network."
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "title",
                    "status",
                    "scheduled_at",
                    "timezone",
                    "labels",
                    "notes",
                    "networks",
                    "variants",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "A social post: your own text, pictures and videos, one version per network."
                },
                "example": {
                  "id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "object": "social_post",
                  "title": "Winter staffing",
                  "status": "draft",
                  "scheduled_at": null,
                  "timezone": null,
                  "labels": [
                    "winter"
                  ],
                  "notes": "",
                  "networks": [
                    "linkedin",
                    "instagram"
                  ],
                  "variants": [
                    {
                      "network": "linkedin",
                      "network_name": "LinkedIn",
                      "content": "Clinics plan their winter staffing now. We place licensed nurses within 48 hours.",
                      "media_urls": [],
                      "status": "pending",
                      "published_at": null,
                      "problem": null
                    },
                    {
                      "network": "instagram",
                      "network_name": "Instagram",
                      "content": "Winter is coming — so are our nurses.",
                      "media_urls": [
                        "https://media.example.com/social-media/6a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d/2f3e4d5c-6b7a-4c8d-9e0f-1a2b3c4d5e6f.jpg"
                      ],
                      "status": "pending",
                      "published_at": null,
                      "problem": null
                    }
                  ],
                  "created_at": "2026-11-05T09:12:33.120Z",
                  "updated_at": "2026-11-05T09:20:01.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "social:publish",
        "x-norreach-action": "social.publish",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/social/posts/{id}": {
      "delete": {
        "operationId": "delete_social_post",
        "summary": "Delete a social post",
        "description": "Deletes a post and the media uploaded for it (a scheduled post then never goes out). A post that is going out right now can't be deleted (409). Copies already published stay on the networks — delete them there. `dry_run=true` checks it and changes nothing.\n\nRequires the `social:publish` scope (reaches people, spends or publishes).",
        "tags": [
          "Social"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "social:publish"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Delete a social post",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "social_post_action"
                    },
                    "post_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "schedule",
                        "unschedule",
                        "delete"
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "changed": {
                      "type": "boolean",
                      "description": "false when there was nothing to do (or on a dry run)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "idea",
                        "draft",
                        "in_review",
                        "scheduled",
                        "publishing",
                        "published",
                        "failed",
                        "deleted"
                      ],
                      "description": "The post's status now (or after it, on a dry run)."
                    },
                    "scheduled_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "post_id",
                    "action",
                    "dry_run",
                    "changed",
                    "status",
                    "scheduled_at",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "What scheduling, unscheduling or deleting a post did — or, on a dry run, would do."
                },
                "example": {
                  "object": "social_post_action",
                  "post_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "action": "delete",
                  "dry_run": false,
                  "changed": true,
                  "status": "deleted",
                  "scheduled_at": null,
                  "note": "Deleted, with its uploaded media."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "social:publish",
        "x-norreach-action": "social.publish",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      },
      "get": {
        "operationId": "get_social_post",
        "summary": "Get a social post",
        "description": "One social post with its version per network: the text, the media addresses, whether each network's copy is pending, publishing, published or failed (with a plain sentence when it failed), and when it is scheduled.\n\nRequires the `social:read` scope.",
        "tags": [
          "Social"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "social:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a social post",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "social_post"
                    },
                    "title": {
                      "type": "string",
                      "description": "The post's name in the calendar (never published)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "idea",
                        "draft",
                        "in_review",
                        "scheduled",
                        "publishing",
                        "published",
                        "failed"
                      ],
                      "description": "idea, draft, in_review, scheduled, publishing, published or failed."
                    },
                    "scheduled_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "When it goes out (scheduled posts)."
                    },
                    "timezone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The IANA time zone it was scheduled in, for display."
                    },
                    "labels": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "notes": {
                      "type": "string",
                      "description": "Internal notes (never published)."
                    },
                    "networks": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "linkedin",
                          "x",
                          "instagram",
                          "facebook",
                          "tiktok"
                        ],
                        "description": "linkedin, x, instagram, facebook or tiktok."
                      }
                    },
                    "variants": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "network": {
                            "type": "string",
                            "enum": [
                              "linkedin",
                              "x",
                              "instagram",
                              "facebook",
                              "tiktok"
                            ],
                            "description": "linkedin, x, instagram, facebook or tiktok."
                          },
                          "network_name": {
                            "type": "string"
                          },
                          "content": {
                            "type": "string",
                            "description": "The text for this network."
                          },
                          "media_urls": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Pictures and videos, in order (public https addresses)."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "publishing",
                              "published",
                              "failed"
                            ],
                            "description": "`pending` (not sent yet), `publishing`, `published` or `failed`."
                          },
                          "published_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "problem": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "When this network's publish failed: a plain sentence (the details are in the app)."
                          }
                        },
                        "required": [
                          "network",
                          "network_name",
                          "content",
                          "media_urls",
                          "status",
                          "published_at",
                          "problem"
                        ],
                        "additionalProperties": false,
                        "description": "The post's version for one network."
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "title",
                    "status",
                    "scheduled_at",
                    "timezone",
                    "labels",
                    "notes",
                    "networks",
                    "variants",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "A social post: your own text, pictures and videos, one version per network."
                },
                "example": {
                  "id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "object": "social_post",
                  "title": "Winter staffing",
                  "status": "scheduled",
                  "scheduled_at": "2026-11-12T08:30:00.000Z",
                  "timezone": "Europe/Stockholm",
                  "labels": [
                    "winter"
                  ],
                  "notes": "",
                  "networks": [
                    "linkedin",
                    "instagram"
                  ],
                  "variants": [
                    {
                      "network": "linkedin",
                      "network_name": "LinkedIn",
                      "content": "Clinics plan their winter staffing now. We place licensed nurses within 48 hours.",
                      "media_urls": [],
                      "status": "pending",
                      "published_at": null,
                      "problem": null
                    },
                    {
                      "network": "instagram",
                      "network_name": "Instagram",
                      "content": "Winter is coming — so are our nurses.",
                      "media_urls": [
                        "https://media.example.com/social-media/6a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d/2f3e4d5c-6b7a-4c8d-9e0f-1a2b3c4d5e6f.jpg"
                      ],
                      "status": "pending",
                      "published_at": null,
                      "problem": null
                    }
                  ],
                  "created_at": "2026-11-05T09:12:33.120Z",
                  "updated_at": "2026-11-05T09:20:01.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "social:read",
        "x-norreach-action": null,
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_social_post",
        "summary": "Change a social post",
        "description": "Changes a post that isn't on the calendar: its title, labels, notes, status (idea, draft or in_review) and — when `variants` is sent — its versions, which then REPLACE the stored ones (networks left out are removed; omit `variants` to keep them). A scheduled post must be unscheduled first; a post going out or published can't be changed (409). A network's copy that already went out can't be rewritten or removed (409). Media in another workspace's files are refused (422).\n\nRequires the `social:publish` scope (reaches people, spends or publishes).",
        "tags": [
          "Social"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "social:publish"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "The post's name in the calendar (never published)."
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "idea",
                      "draft",
                      "in_review"
                    ],
                    "description": "idea, draft (default) or in_review — scheduling has its own operation."
                  },
                  "labels": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 50
                    }
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 5000,
                    "description": "Internal notes (never published)."
                  },
                  "variants": {
                    "description": "REPLACES the post's versions: networks left out are removed, the ones given are written as sent. Omit to keep them.",
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "network": {
                          "type": "string",
                          "enum": [
                            "linkedin",
                            "x",
                            "instagram",
                            "facebook",
                            "tiktok"
                          ],
                          "description": "linkedin, x, instagram, facebook or tiktok."
                        },
                        "content": {
                          "default": "",
                          "description": "The text for this network (each network's own limit is checked when scheduling: X 280, LinkedIn 3000, Instagram 2200, Facebook 5000, TikTok 2200).",
                          "type": "string",
                          "maxLength": 10000
                        },
                        "media_urls": {
                          "default": [],
                          "description": "Up to 10 pictures or videos. Instagram needs at least one to be scheduled.",
                          "maxItems": 10,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "maxLength": 2000,
                            "description": "A public http(s) address of a picture or video (e.g. a `media_url` from POST /social/uploads)."
                          }
                        }
                      },
                      "required": [
                        "network"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "title": "Winter staffing — week 46",
                "variants": [
                  {
                    "network": "linkedin",
                    "content": "Clinics plan their winter staffing now. We place licensed nurses within 48 hours."
                  },
                  {
                    "network": "instagram",
                    "content": "Winter is coming — so are our nurses.",
                    "media_urls": [
                      "https://media.example.com/social-media/6a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d/2f3e4d5c-6b7a-4c8d-9e0f-1a2b3c4d5e6f.jpg"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Change a social post",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "social_post"
                    },
                    "title": {
                      "type": "string",
                      "description": "The post's name in the calendar (never published)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "idea",
                        "draft",
                        "in_review",
                        "scheduled",
                        "publishing",
                        "published",
                        "failed"
                      ],
                      "description": "idea, draft, in_review, scheduled, publishing, published or failed."
                    },
                    "scheduled_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "When it goes out (scheduled posts)."
                    },
                    "timezone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The IANA time zone it was scheduled in, for display."
                    },
                    "labels": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "notes": {
                      "type": "string",
                      "description": "Internal notes (never published)."
                    },
                    "networks": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "linkedin",
                          "x",
                          "instagram",
                          "facebook",
                          "tiktok"
                        ],
                        "description": "linkedin, x, instagram, facebook or tiktok."
                      }
                    },
                    "variants": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "network": {
                            "type": "string",
                            "enum": [
                              "linkedin",
                              "x",
                              "instagram",
                              "facebook",
                              "tiktok"
                            ],
                            "description": "linkedin, x, instagram, facebook or tiktok."
                          },
                          "network_name": {
                            "type": "string"
                          },
                          "content": {
                            "type": "string",
                            "description": "The text for this network."
                          },
                          "media_urls": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Pictures and videos, in order (public https addresses)."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "publishing",
                              "published",
                              "failed"
                            ],
                            "description": "`pending` (not sent yet), `publishing`, `published` or `failed`."
                          },
                          "published_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "problem": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "When this network's publish failed: a plain sentence (the details are in the app)."
                          }
                        },
                        "required": [
                          "network",
                          "network_name",
                          "content",
                          "media_urls",
                          "status",
                          "published_at",
                          "problem"
                        ],
                        "additionalProperties": false,
                        "description": "The post's version for one network."
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "title",
                    "status",
                    "scheduled_at",
                    "timezone",
                    "labels",
                    "notes",
                    "networks",
                    "variants",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "A social post: your own text, pictures and videos, one version per network."
                },
                "example": {
                  "id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "object": "social_post",
                  "title": "Winter staffing — week 46",
                  "status": "draft",
                  "scheduled_at": null,
                  "timezone": null,
                  "labels": [
                    "winter"
                  ],
                  "notes": "",
                  "networks": [
                    "linkedin",
                    "instagram"
                  ],
                  "variants": [
                    {
                      "network": "linkedin",
                      "network_name": "LinkedIn",
                      "content": "Clinics plan their winter staffing now. We place licensed nurses within 48 hours.",
                      "media_urls": [],
                      "status": "pending",
                      "published_at": null,
                      "problem": null
                    },
                    {
                      "network": "instagram",
                      "network_name": "Instagram",
                      "content": "Winter is coming — so are our nurses.",
                      "media_urls": [
                        "https://media.example.com/social-media/6a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d/2f3e4d5c-6b7a-4c8d-9e0f-1a2b3c4d5e6f.jpg"
                      ],
                      "status": "pending",
                      "published_at": null,
                      "problem": null
                    }
                  ],
                  "created_at": "2026-11-05T09:12:33.120Z",
                  "updated_at": "2026-11-05T09:20:01.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "social:publish",
        "x-norreach-action": "social.publish",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/social/posts/{id}/schedule": {
      "post": {
        "operationId": "schedule_social_post",
        "summary": "Schedule a social post",
        "description": "Puts a post on the calendar: at `at` it is published to every network it has a version for, through the connected profiles — exactly as the app's Schedule button. It needs the social.publish role, outreach must not be paused (409 outreach_paused; if outreach is paused later, the post waits until it resumes), and the post must pass the calendar's checks (422 post_schedule_blocked with a `reason`: no_networks, empty_text, too_long, account_not_connected, instagram_media_required, too_many_media). Scheduling a scheduled post again moves it. `dry_run=true` runs every check and changes nothing.\n\nRequires the `social:publish` scope (reaches people, spends or publishes).",
        "tags": [
          "Social"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "social:publish"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "at": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "description": "When it goes out (RFC 3339). A time in the past goes out within a minute or two."
                  },
                  "timezone": {
                    "description": "The IANA time zone to show it in (e.g. Europe/Stockholm). Display only.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  }
                },
                "required": [
                  "at"
                ],
                "additionalProperties": false
              },
              "example": {
                "at": "2026-11-12T08:30:00Z",
                "timezone": "Europe/Stockholm"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Schedule a social post",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "social_post_action"
                    },
                    "post_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "schedule",
                        "unschedule",
                        "delete"
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "changed": {
                      "type": "boolean",
                      "description": "false when there was nothing to do (or on a dry run)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "idea",
                        "draft",
                        "in_review",
                        "scheduled",
                        "publishing",
                        "published",
                        "failed",
                        "deleted"
                      ],
                      "description": "The post's status now (or after it, on a dry run)."
                    },
                    "scheduled_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "post_id",
                    "action",
                    "dry_run",
                    "changed",
                    "status",
                    "scheduled_at",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "What scheduling, unscheduling or deleting a post did — or, on a dry run, would do."
                },
                "example": {
                  "object": "social_post_action",
                  "post_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "action": "schedule",
                  "dry_run": false,
                  "changed": true,
                  "status": "scheduled",
                  "scheduled_at": "2026-11-12T08:30:00.000Z",
                  "note": "Scheduled — it goes out at that time unless outreach is paused then (it waits until outreach resumes)."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request. · `post_schedule_blocked` — This post can't be scheduled yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "social:publish",
        "x-norreach-action": "social.publish",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/social/posts/{id}/unschedule": {
      "post": {
        "operationId": "unschedule_social_post",
        "summary": "Unschedule a social post",
        "description": "Takes a scheduled post off the calendar: it goes back to a draft and nothing goes out. Works while outreach is paused. A post that isn't scheduled answers `changed: false`; one that is going out right now or published is a conflict (409). `dry_run=true` checks it and changes nothing.\n\nRequires the `social:publish` scope (reaches people, spends or publishes).",
        "tags": [
          "Social"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "social:publish"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Unschedule a social post",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "social_post_action"
                    },
                    "post_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "schedule",
                        "unschedule",
                        "delete"
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "changed": {
                      "type": "boolean",
                      "description": "false when there was nothing to do (or on a dry run)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "idea",
                        "draft",
                        "in_review",
                        "scheduled",
                        "publishing",
                        "published",
                        "failed",
                        "deleted"
                      ],
                      "description": "The post's status now (or after it, on a dry run)."
                    },
                    "scheduled_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "post_id",
                    "action",
                    "dry_run",
                    "changed",
                    "status",
                    "scheduled_at",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "What scheduling, unscheduling or deleting a post did — or, on a dry run, would do."
                },
                "example": {
                  "object": "social_post_action",
                  "post_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "action": "unschedule",
                  "dry_run": false,
                  "changed": true,
                  "status": "draft",
                  "scheduled_at": null,
                  "note": "Unscheduled — it is a draft again and nothing goes out."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "social:publish",
        "x-norreach-action": "social.publish",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/social/uploads": {
      "post": {
        "operationId": "create_social_upload",
        "summary": "Upload a picture or video for a post",
        "description": "Reserves a place for one file in the workspace's media and answers a single-use upload address (valid for 2 hours): PUT the file's bytes there with the given Content-Type, then put `media_url` in a version's `media_urls`. JPEG, PNG, WebP or GIF pictures up to 10 MB, MP4 videos up to 50 MB. The upload address is a secret — don't log or share it.\n\nRequires the `social:publish` scope (reaches people, spends or publishes).",
        "tags": [
          "Social"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "social:publish"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content_type": {
                    "type": "string",
                    "enum": [
                      "image/jpeg",
                      "image/png",
                      "image/webp",
                      "image/gif",
                      "video/mp4"
                    ],
                    "description": "image/jpeg, image/png, image/webp, image/gif or video/mp4."
                  },
                  "size_bytes": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991,
                    "description": "The file's size. Pictures up to 10 MB, videos up to 50 MB."
                  },
                  "filename": {
                    "description": "Only used in error messages.",
                    "type": "string",
                    "maxLength": 200
                  }
                },
                "required": [
                  "content_type",
                  "size_bytes"
                ],
                "additionalProperties": false
              },
              "example": {
                "content_type": "image/jpeg",
                "size_bytes": 482113,
                "filename": "nurses.jpg"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Upload a picture or video for a post",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "social_upload"
                    },
                    "media_url": {
                      "type": "string",
                      "description": "Where the file will be served once uploaded — put this in a variant's `media_urls`."
                    },
                    "upload": {
                      "type": "object",
                      "properties": {
                        "method": {
                          "type": "string",
                          "const": "PUT"
                        },
                        "url": {
                          "type": "string",
                          "description": "A single-use, pre-signed address on NorReach's media store. Treat it as opaque and secret."
                        },
                        "headers": {
                          "type": "object",
                          "properties": {
                            "Content-Type": {
                              "type": "string",
                              "enum": [
                                "image/jpeg",
                                "image/png",
                                "image/webp",
                                "image/gif",
                                "video/mp4"
                              ]
                            }
                          },
                          "required": [
                            "Content-Type"
                          ],
                          "additionalProperties": false
                        },
                        "expires_at": {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        }
                      },
                      "required": [
                        "method",
                        "url",
                        "headers",
                        "expires_at"
                      ],
                      "additionalProperties": false,
                      "description": "Send the file's bytes as the request body, with exactly these headers, before `expires_at`."
                    },
                    "content_type": {
                      "type": "string",
                      "enum": [
                        "image/jpeg",
                        "image/png",
                        "image/webp",
                        "image/gif",
                        "video/mp4"
                      ]
                    },
                    "max_bytes": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "The largest file this type may be."
                    }
                  },
                  "required": [
                    "object",
                    "media_url",
                    "upload",
                    "content_type",
                    "max_bytes"
                  ],
                  "additionalProperties": false,
                  "description": "A place to upload one picture or video for a post."
                },
                "example": {
                  "object": "social_upload",
                  "media_url": "https://media.example.com/social-media/6a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d/2f3e4d5c-6b7a-4c8d-9e0f-1a2b3c4d5e6f.jpg",
                  "upload": {
                    "method": "PUT",
                    "url": "https://media.example.com/upload/sign/social-media/6a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d/2f3e4d5c-6b7a-4c8d-9e0f-1a2b3c4d5e6f.jpg?token=…",
                    "headers": {
                      "Content-Type": "image/jpeg"
                    },
                    "expires_at": "2026-11-05T11:12:33.120Z"
                  },
                  "content_type": "image/jpeg",
                  "max_bytes": 10485760
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "social:publish",
        "x-norreach-action": "social.publish",
        "x-norreach-phase": "C",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/suppressions": {
      "get": {
        "operationId": "list_suppressions",
        "summary": "List do-not-contact entries",
        "description": "Everything that blocks sending: email addresses and phone numbers (unsubscribes, complaints, bounces, entries you added), company domains, LinkedIn URLs, and fingerprints of erased people. Newest first; filter with `kind`.\n\nRequires the `contacts:read` scope.",
        "tags": [
          "Do-not-contact"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "email",
                "phone",
                "domain",
                "linkedin",
                "erased"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List do-not-contact entries",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "suppression"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "email",
                              "phone",
                              "domain",
                              "linkedin",
                              "erased"
                            ],
                            "description": "`erased` = a person whose data was erased; only a fingerprint is kept, so `value` is null."
                          },
                          "value": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "reason": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "kind",
                          "value",
                          "reason",
                          "created_at"
                        ],
                        "additionalProperties": false,
                        "description": "A do-not-contact entry: nothing is sent to anyone it matches."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "3e4f5a6b-7c8d-4e9f-8a0b-1c2d3e4f5a6b",
                      "object": "suppression",
                      "kind": "email",
                      "value": "no.thanks@example.com",
                      "reason": "unsubscribed",
                      "created_at": "2026-11-04T09:12:33.120Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "create_suppression",
        "summary": "Add a do-not-contact entry",
        "description": "Blocks every send to an email address, a phone number, a company domain (and its sub-domains) or a LinkedIn URL — for automated outreach and replies alike. Adding an entry that already exists returns it (200).\n\nRequires the `suppressions:write` scope (reaches people, spends or publishes).",
        "tags": [
          "Do-not-contact"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "suppressions:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "email",
                      "phone",
                      "domain",
                      "linkedin"
                    ]
                  },
                  "value": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 500
                  },
                  "reason": {
                    "description": "Email and phone entries only. Defaults to `manual`.",
                    "type": "string",
                    "enum": [
                      "manual",
                      "do_not_contact",
                      "unsubscribed",
                      "complaint",
                      "bounced"
                    ]
                  }
                },
                "required": [
                  "kind",
                  "value"
                ],
                "additionalProperties": false
              },
              "example": {
                "kind": "email",
                "value": "no.thanks@example.com",
                "reason": "do_not_contact"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Add a do-not-contact entry",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "suppression"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "email",
                        "phone",
                        "domain",
                        "linkedin",
                        "erased"
                      ],
                      "description": "`erased` = a person whose data was erased; only a fingerprint is kept, so `value` is null."
                    },
                    "value": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "reason": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "kind",
                    "value",
                    "reason",
                    "created_at"
                  ],
                  "additionalProperties": false,
                  "description": "A do-not-contact entry: nothing is sent to anyone it matches."
                },
                "example": {
                  "id": "3e4f5a6b-7c8d-4e9f-8a0b-1c2d3e4f5a6b",
                  "object": "suppression",
                  "kind": "email",
                  "value": "no.thanks@example.com",
                  "reason": "do_not_contact",
                  "created_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "suppressions:write",
        "x-norreach-action": "settings.compliance",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/tags": {
      "get": {
        "operationId": "list_tags",
        "summary": "List tags",
        "description": "Every tag in the workspace with how many contacts carry it, most used first. Counts cover the newest 20 000 contacts (`counts_capped` says when there are more).\n\nRequires the `contacts:read` scope.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "contacts:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List tags",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "const": "tag"
                          },
                          "name": {
                            "type": "string"
                          },
                          "contacts": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "object",
                          "name",
                          "contacts"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "const": false
                    },
                    "next_cursor": {
                      "type": "null"
                    },
                    "counts_capped": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor",
                    "counts_capped"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "tag",
                      "name": "webinar",
                      "contacts": 42
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null,
                  "counts_capped": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "contacts:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/team-requests": {
      "get": {
        "operationId": "list_team_requests",
        "summary": "List the team's requests",
        "description": "The requests people in the workspace raised in Team › Requests, newest first, as an owner or admin sees them. Filter by `status` and `priority`. Owners and admins.\n\nRequires the `team:requests` scope.",
        "tags": [
          "Team"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "team:requests"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "in_progress",
                "resolved",
                "closed"
              ]
            }
          },
          {
            "name": "priority",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "low",
                "medium",
                "high",
                "urgent"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List the team's requests",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "team_request"
                          },
                          "title": {
                            "type": "string"
                          },
                          "description": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "open",
                              "in_progress",
                              "resolved",
                              "closed"
                            ]
                          },
                          "priority": {
                            "type": "string",
                            "enum": [
                              "low",
                              "medium",
                              "high",
                              "urgent"
                            ]
                          },
                          "category": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_by": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "updated_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "title",
                          "description",
                          "status",
                          "priority",
                          "category",
                          "created_by",
                          "created_at",
                          "updated_at"
                        ],
                        "additionalProperties": false,
                        "description": "A request someone in the team raised (Team › Requests)."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f",
                      "object": "team_request",
                      "title": "Can't see the Stockholm number",
                      "description": "It's gone from my caller ID list.",
                      "status": "open",
                      "priority": "high",
                      "category": "technical",
                      "created_by": "8e9f0a1b-2c3d-4e4f-9a5b-6c7d8e9f0a1b",
                      "created_at": "2026-11-04T09:00:00.000Z",
                      "updated_at": "2026-11-04T09:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "team:requests",
        "x-norreach-action": "team.requests",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/team-requests/{id}": {
      "get": {
        "operationId": "get_team_request",
        "summary": "Get a request",
        "description": "One of the team's requests with its replies (internal notes included — owners and admins see them).\n\nRequires the `team:requests` scope.",
        "tags": [
          "Team"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "team:requests"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "team_request"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "open",
                        "in_progress",
                        "resolved",
                        "closed"
                      ]
                    },
                    "priority": {
                      "type": "string",
                      "enum": [
                        "low",
                        "medium",
                        "high",
                        "urgent"
                      ]
                    },
                    "category": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_by": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updated_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "replies": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "team_request_reply"
                          },
                          "content": {
                            "type": "string"
                          },
                          "internal": {
                            "type": "boolean",
                            "description": "A note for owners and admins."
                          },
                          "author_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "content",
                          "internal",
                          "author_id",
                          "created_at"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "title",
                    "description",
                    "status",
                    "priority",
                    "category",
                    "created_by",
                    "created_at",
                    "updated_at",
                    "replies"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f",
                  "object": "team_request",
                  "title": "Can't see the Stockholm number",
                  "description": "It's gone from my caller ID list.",
                  "status": "open",
                  "priority": "high",
                  "category": "technical",
                  "created_by": "8e9f0a1b-2c3d-4e4f-9a5b-6c7d8e9f0a1b",
                  "created_at": "2026-11-04T09:00:00.000Z",
                  "updated_at": "2026-11-04T09:00:00.000Z",
                  "replies": [
                    {
                      "id": "3d4e5f6a-7b8c-4d9e-8f0a-1b2c3d4e5f6a",
                      "object": "team_request_reply",
                      "content": "Looking at it now.",
                      "internal": false,
                      "author_id": "4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b",
                      "created_at": "2026-11-04T09:20:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "team:requests",
        "x-norreach-action": "team.requests",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_team_request",
        "summary": "Decide a request",
        "description": "Moves a request on — its `status` (open, in_progress, resolved, closed) and / or `priority` (low, medium, high, urgent) — as Team › Requests does: one activity entry per change, and the person who raised it is told. Owners and admins. `dry_run=true` answers it as it would be.\n\nRequires the `team:requests` scope.",
        "tags": [
          "Team"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "team:requests"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "open",
                      "in_progress",
                      "resolved",
                      "closed"
                    ]
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "medium",
                      "high",
                      "urgent"
                    ]
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "status": "resolved"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Decide a request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "team_request"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "open",
                        "in_progress",
                        "resolved",
                        "closed"
                      ]
                    },
                    "priority": {
                      "type": "string",
                      "enum": [
                        "low",
                        "medium",
                        "high",
                        "urgent"
                      ]
                    },
                    "category": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_by": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updated_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "title",
                    "description",
                    "status",
                    "priority",
                    "category",
                    "created_by",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "A request someone in the team raised (Team › Requests)."
                },
                "example": {
                  "id": "2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f",
                  "object": "team_request",
                  "title": "Can't see the Stockholm number",
                  "description": "It's gone from my caller ID list.",
                  "status": "resolved",
                  "priority": "high",
                  "category": "technical",
                  "created_by": "8e9f0a1b-2c3d-4e4f-9a5b-6c7d8e9f0a1b",
                  "created_at": "2026-11-04T09:00:00.000Z",
                  "updated_at": "2026-11-04T09:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "team:requests",
        "x-norreach-action": "team.requests",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/team-requests/{id}/replies": {
      "post": {
        "operationId": "reply_to_team_request",
        "summary": "Reply to a request",
        "description": "Adds a reply to a request — or, with `internal: true`, a note for owners and admins. The person who raised it is told. Owners and admins. `dry_run=true` saves nothing.\n\nRequires the `team:requests` scope.",
        "tags": [
          "Team"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "team:requests"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000
                  },
                  "internal": {
                    "default": false,
                    "type": "boolean"
                  }
                },
                "required": [
                  "content"
                ],
                "additionalProperties": false
              },
              "example": {
                "content": "Fixed — it's back on your list."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Reply to a request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "team_request_reply"
                    },
                    "content": {
                      "type": "string"
                    },
                    "internal": {
                      "type": "boolean",
                      "description": "A note for owners and admins."
                    },
                    "author_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "content",
                    "internal",
                    "author_id",
                    "created_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "3d4e5f6a-7b8c-4d9e-8f0a-1b2c3d4e5f6a",
                  "object": "team_request_reply",
                  "content": "Fixed — it's back on your list.",
                  "internal": false,
                  "author_id": "4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b",
                  "created_at": "2026-11-05T10:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "team:requests",
        "x-norreach-action": "team.requests",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/templates": {
      "get": {
        "operationId": "list_templates",
        "summary": "Message and WhatsApp templates",
        "description": "The workspace's saved message templates and its WhatsApp templates with their review state — only APPROVED WhatsApp templates can be sent (POST /messages `template`).\n\nRequires the `inbox:read` scope.",
        "tags": [
          "Inbox"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "inbox:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "message",
                "whatsapp"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Message and WhatsApp templates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "template"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "message",
                              "whatsapp"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "channel": {
                            "type": "string"
                          },
                          "language": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "category": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "WhatsApp: the network's review state (only APPROVED templates can be sent)."
                          },
                          "subject": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "body": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "variable_count": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "kind",
                          "name",
                          "channel",
                          "language",
                          "category",
                          "status",
                          "subject",
                          "body",
                          "variable_count"
                        ],
                        "additionalProperties": false,
                        "description": "A saved message template or a WhatsApp template."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "6f7a8b9c-0d1e-4f2a-9b3c-4d5e6f7a8b9c",
                      "object": "template",
                      "kind": "whatsapp",
                      "name": "follow_up",
                      "channel": "whatsapp",
                      "language": "sv",
                      "category": "MARKETING",
                      "status": "APPROVED",
                      "subject": null,
                      "body": "Hej {{1}}, …",
                      "variable_count": 1
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "inbox:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "create_message_template",
        "summary": "Save a message template",
        "description": "Saves an email, SMS or WhatsApp-body template in Campaigns › Templates — your own words (a subject for email). The app's own trimming and limits (name 120, category 60, subject 200, body 100,000 characters). Owners, admins and managers. `dry_run=true` answers it as it would be saved.\n\nRequires the `templates:write` scope.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "templates:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "email",
                      "sms",
                      "whatsapp"
                    ]
                  },
                  "category": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "subject": {
                    "description": "Email only.",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100000
                  }
                },
                "required": [
                  "name",
                  "channel",
                  "body"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "First touch",
                "channel": "email",
                "category": "Outreach",
                "subject": "Nurses when you need them",
                "body": "Hi {{first_name}}, …"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Save a message template",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "template"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "message",
                        "whatsapp"
                      ]
                    },
                    "name": {
                      "type": "string"
                    },
                    "channel": {
                      "type": "string"
                    },
                    "language": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "category": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "WhatsApp: the network's review state (only APPROVED templates can be sent)."
                    },
                    "subject": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "body": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "variable_count": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "kind",
                    "name",
                    "channel",
                    "language",
                    "category",
                    "status",
                    "subject",
                    "body",
                    "variable_count"
                  ],
                  "additionalProperties": false,
                  "description": "A saved message template or a WhatsApp template."
                },
                "example": {
                  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                  "object": "template",
                  "kind": "message",
                  "name": "First touch",
                  "channel": "email",
                  "language": null,
                  "category": "Outreach",
                  "status": null,
                  "subject": "Nurses when you need them",
                  "body": "Hi {{first_name}}, …",
                  "variable_count": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "templates:write",
        "x-norreach-action": "channels.templates",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/templates/{id}": {
      "delete": {
        "operationId": "delete_message_template",
        "summary": "Delete a message template",
        "description": "Deletes a saved template. Campaigns that copied its words keep them. Owners, admins and managers. `dry_run=true` changes nothing.\n\nRequires the `templates:write` scope.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "templates:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Delete a message template",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "template_deletion"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "deleted": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "deleted",
                    "dry_run"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "template_deletion",
                  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                  "deleted": true,
                  "dry_run": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "templates:write",
        "x-norreach-action": "channels.templates",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_message_template",
        "summary": "Change a message template",
        "description": "Changes a saved template's name, category, subject (email) or body. Its channel stays. Owners, admins and managers. `dry_run=true` answers it as it would be.\n\nRequires the `templates:write` scope.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "templates:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "category": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "subject": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100000
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "subject": "Nurses within 48 hours"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Change a message template",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "template"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "message",
                        "whatsapp"
                      ]
                    },
                    "name": {
                      "type": "string"
                    },
                    "channel": {
                      "type": "string"
                    },
                    "language": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "category": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "WhatsApp: the network's review state (only APPROVED templates can be sent)."
                    },
                    "subject": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "body": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "variable_count": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "kind",
                    "name",
                    "channel",
                    "language",
                    "category",
                    "status",
                    "subject",
                    "body",
                    "variable_count"
                  ],
                  "additionalProperties": false,
                  "description": "A saved message template or a WhatsApp template."
                },
                "example": {
                  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                  "object": "template",
                  "kind": "message",
                  "name": "First touch",
                  "channel": "email",
                  "language": null,
                  "category": "Outreach",
                  "status": null,
                  "subject": "Nurses within 48 hours",
                  "body": "Hi {{first_name}}, …",
                  "variable_count": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "templates:write",
        "x-norreach-action": "channels.templates",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/threads": {
      "get": {
        "operationId": "list_threads",
        "summary": "List conversations",
        "description": "The inbox's conversations, most recent activity first. Filter by `channel`, `unread`, `contact_id` or `campaign_id` (contacts enrolled in that campaign).\n\nRequires the `inbox:read` scope.",
        "tags": [
          "Inbox"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "inbox:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "email",
                "sms",
                "whatsapp",
                "linkedin"
              ]
            }
          },
          {
            "name": "unread",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "campaign_id",
            "in": "query",
            "required": false,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "default": "open",
              "type": "string",
              "enum": [
                "open",
                "closed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List conversations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "thread"
                          },
                          "channel": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "email, sms, whatsapp or linkedin."
                          },
                          "subject": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "type": "string"
                          },
                          "unread": {
                            "type": "boolean"
                          },
                          "contact": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                    "description": "An id (UUID)."
                                  },
                                  "name": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "email": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "phone": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "company": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  }
                                },
                                "required": [
                                  "id",
                                  "name",
                                  "email",
                                  "phone",
                                  "company"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "last_message_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "last_inbound_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "When the contact last wrote (WhatsApp's 24-hour window counts from here)."
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "channel",
                          "subject",
                          "status",
                          "unread",
                          "contact",
                          "last_message_at",
                          "last_inbound_at",
                          "created_at"
                        ],
                        "additionalProperties": false,
                        "description": "A conversation with one contact on one channel."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                      "object": "thread",
                      "channel": "email",
                      "subject": "Nurses for the summer",
                      "status": "open",
                      "unread": true,
                      "contact": {
                        "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                        "name": "Maja Lind",
                        "email": "maja.lind@example.com",
                        "phone": "+46701234567",
                        "company": "Example Care AB"
                      },
                      "last_message_at": "2026-11-04T09:12:33.120Z",
                      "last_inbound_at": "2026-11-04T09:12:33.120Z",
                      "created_at": "2026-11-01T08:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "inbox:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/threads/{id}": {
      "get": {
        "operationId": "get_thread",
        "summary": "One conversation",
        "description": "A conversation with its contact.\n\nRequires the `inbox:read` scope.",
        "tags": [
          "Inbox"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "inbox:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One conversation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "thread"
                    },
                    "channel": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "email, sms, whatsapp or linkedin."
                    },
                    "subject": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string"
                    },
                    "unread": {
                      "type": "boolean"
                    },
                    "contact": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            "name": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "email": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "phone": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "company": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "id",
                            "name",
                            "email",
                            "phone",
                            "company"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "last_message_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "last_inbound_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "When the contact last wrote (WhatsApp's 24-hour window counts from here)."
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "channel",
                    "subject",
                    "status",
                    "unread",
                    "contact",
                    "last_message_at",
                    "last_inbound_at",
                    "created_at"
                  ],
                  "additionalProperties": false,
                  "description": "A conversation with one contact on one channel."
                },
                "example": {
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "object": "thread",
                  "channel": "email",
                  "subject": "Nurses for the summer",
                  "status": "open",
                  "unread": true,
                  "contact": {
                    "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                    "name": "Maja Lind",
                    "email": "maja.lind@example.com",
                    "phone": "+46701234567",
                    "company": "Example Care AB"
                  },
                  "last_message_at": "2026-11-04T09:12:33.120Z",
                  "last_inbound_at": "2026-11-04T09:12:33.120Z",
                  "created_at": "2026-11-01T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "inbox:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/threads/{id}/draft": {
      "post": {
        "operationId": "draft_thread_reply",
        "summary": "Draft a reply",
        "description": "Nora drafts the next reply from the conversation so far. Nothing is sent and nothing is saved — send it with POST /threads/{id}/reply. Needs `inbox:read` too.\n\nRequires the `nora:ask` scope.",
        "tags": [
          "Inbox"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "nora:ask"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Draft a reply",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "draft"
                    },
                    "thread_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "text": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "thread_id",
                    "text"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "draft",
                  "thread_id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "text": "Thursday works — would 10:00 suit you?"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "nora:ask",
        "x-norreach-action": "nora.ask",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/threads/{id}/messages": {
      "get": {
        "operationId": "list_thread_messages",
        "summary": "A conversation's messages",
        "description": "The messages of a conversation, oldest first, a page at a time. An outbound message that didn't go out has status `failed` and the reason in `failure`.\n\nRequires the `inbox:read` scope.",
        "tags": [
          "Inbox"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "inbox:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A conversation's messages",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "message"
                          },
                          "thread_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "contact_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "channel": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "direction": {
                            "type": "string",
                            "enum": [
                              "inbound",
                              "outbound"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "description": "queued, sending, sent, delivered, read, failed, bounced … (inbound: received)."
                          },
                          "body": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "source": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "What wrote it: api, automation, a campaign step (null) …"
                          },
                          "campaign_id": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "failure": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Why it didn't go out (status failed), in customer words."
                          },
                          "opened_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "clicked_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "bounced_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "thread_id",
                          "contact_id",
                          "channel",
                          "direction",
                          "status",
                          "body",
                          "source",
                          "campaign_id",
                          "failure",
                          "opened_at",
                          "clicked_at",
                          "bounced_at",
                          "created_at"
                        ],
                        "additionalProperties": false,
                        "description": "One message on a thread."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
                      "object": "message",
                      "thread_id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                      "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                      "channel": "email",
                      "direction": "inbound",
                      "status": "received",
                      "body": "Sounds good — can we talk Thursday?",
                      "source": null,
                      "campaign_id": null,
                      "failure": null,
                      "opened_at": null,
                      "clicked_at": null,
                      "bounced_at": null,
                      "created_at": "2026-11-04T09:12:33.120Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "inbox:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/threads/{id}/read": {
      "post": {
        "operationId": "mark_thread_read",
        "summary": "Mark a conversation read",
        "description": "Clears the unread flag, as opening it in the inbox does.\n\nRequires the `inbox:read` scope.",
        "tags": [
          "Inbox"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "inbox:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Mark a conversation read",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "thread"
                    },
                    "channel": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "email, sms, whatsapp or linkedin."
                    },
                    "subject": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "type": "string"
                    },
                    "unread": {
                      "type": "boolean"
                    },
                    "contact": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            "name": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "email": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "phone": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "company": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "id",
                            "name",
                            "email",
                            "phone",
                            "company"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "last_message_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "last_inbound_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "When the contact last wrote (WhatsApp's 24-hour window counts from here)."
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "channel",
                    "subject",
                    "status",
                    "unread",
                    "contact",
                    "last_message_at",
                    "last_inbound_at",
                    "created_at"
                  ],
                  "additionalProperties": false,
                  "description": "A conversation with one contact on one channel."
                },
                "example": {
                  "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
                  "object": "thread",
                  "channel": "email",
                  "subject": "Nurses for the summer",
                  "status": "open",
                  "unread": false,
                  "contact": {
                    "id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                    "name": "Maja Lind",
                    "email": "maja.lind@example.com",
                    "phone": "+46701234567",
                    "company": "Example Care AB"
                  },
                  "last_message_at": "2026-11-04T09:12:33.120Z",
                  "last_inbound_at": "2026-11-04T09:12:33.120Z",
                  "created_at": "2026-11-01T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "inbox:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/threads/{id}/reply": {
      "post": {
        "operationId": "reply_to_thread",
        "summary": "Reply on a conversation",
        "description": "Asks for a reply on the conversation's channel (email, SMS or WhatsApp). It is an API send: it waits in Approvals when the workspace approves before sending or the key lacks `approvals:decide`; `approve: true` (with `approvals:decide`) approves it in the same request. Suppressed, do-not-contact, no lawful basis or quiet hours answer 422 send_blocked with the `reason`. On WhatsApp outside the 24-hour window only an approved `template` can be sent. LinkedIn replies aren't available through the API.\n\nRequires the `messages:send` scope (reaches people, spends or publishes).",
        "tags": [
          "Inbox"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "messages:send"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "description": "The reply (required unless `template`).",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000
                  },
                  "template": {
                    "description": "WhatsApp only: an approved template (required outside the 24-hour window).",
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 512,
                        "description": "An approved WhatsApp template of this workspace (GET /templates)."
                      },
                      "language": {
                        "description": "Its language code, e.g. sv or en_US (default: the template's own).",
                        "type": "string",
                        "maxLength": 20
                      },
                      "params": {
                        "default": [],
                        "description": "Values for the template's variables, in order.",
                        "maxItems": 20,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "maxLength": 1024
                        }
                      }
                    },
                    "required": [
                      "name"
                    ],
                    "additionalProperties": false
                  },
                  "approve": {
                    "default": false,
                    "description": "Approve it now as the key's creator (needs approvals:decide).",
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "text": "Thursday at 10 works — I'll send an invite."
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Reply on a conversation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "send_request"
                    },
                    "id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The request's id — poll GET /messages/{id} or GET /calls/{id} with it."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "message",
                        "call"
                      ]
                    },
                    "channel": {
                      "type": "string"
                    },
                    "contact_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "awaiting_approval",
                        "queued",
                        "dry_run"
                      ],
                      "description": "awaiting_approval = it waits in Approvals; queued = approved, it goes out within a minute through the send checks."
                    },
                    "approval_key": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The Approvals key (approve it with POST /approvals/{key}/approve)."
                    },
                    "note": {
                      "type": "string"
                    },
                    "would": {
                      "description": "Dry run: what would happen.",
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "awaiting_approval",
                            "queued"
                          ]
                        }
                      },
                      "required": [
                        "status"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "kind",
                    "channel",
                    "contact_id",
                    "status",
                    "approval_key",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "A send asked for through the API. It never skips the send checks or the approval queue."
                },
                "example": {
                  "object": "send_request",
                  "id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "kind": "message",
                  "channel": "email",
                  "contact_id": "7d1c3b2a-5e4f-4a1b-9c8d-0e1f2a3b4c5d",
                  "status": "awaiting_approval",
                  "approval_key": "rule_send:5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "note": "It waits in Approvals until someone says yes."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `outreach_paused` — Outreach is paused for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request. · `send_blocked` — This can't be sent to this person.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again. · `send_cap_reached` — The workspace's sending limit for now is reached.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "messages:send",
        "x-norreach-action": "inbox.reply",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": true
      }
    },
    "/versions/{id}": {
      "get": {
        "operationId": "get_page_version",
        "summary": "One page version",
        "description": "A saved version's content and its content checks.\n\nRequires the `pages:read` scope.",
        "tags": [
          "Landing pages"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "pages:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page version",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "page_version"
                    },
                    "page_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "number": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "author_kind": {
                      "type": "string",
                      "description": "Who made it: nora or user."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "holds": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Content checks that would hold it back."
                    },
                    "content": {},
                    "checks": {}
                  },
                  "required": [
                    "id",
                    "object",
                    "page_id",
                    "number",
                    "author_kind",
                    "created_at",
                    "note",
                    "holds",
                    "content",
                    "checks"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "8c9d0e1f-2a3b-4c4d-9e5f-6a7b8c9d0e1f",
                  "object": "page_version",
                  "page_id": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                  "number": 3,
                  "author_kind": "user",
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "note": null,
                  "holds": [],
                  "content": {},
                  "checks": {}
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "pages:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/voice-agents": {
      "get": {
        "operationId": "list_voice_agents",
        "summary": "Your voice agents",
        "description": "The AI caller's configured agents (name, description, language) — pass one as `voice_agent_id` to POST /calls.\n\nRequires the `calls:read` scope.",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "calls:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Your voice agents",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "voice_agent"
                          },
                          "name": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "description": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "language": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "name",
                          "description",
                          "language",
                          "created_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "9c0d1e2f-3a4b-4c5d-8e6f-7a8b9c0d1e2f",
                      "object": "voice_agent",
                      "name": "Nora — staffing",
                      "description": "Books intro calls",
                      "language": "sv",
                      "created_at": "2026-10-01T08:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "calls:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "create_voice_agent",
        "summary": "Create a voice agent",
        "description": "Creates an agent for the AI caller — name, language, first message, script (your own words), a voice (GET /voices) and a number (GET /phone-numbers) — as the app's agent editor saves it. It starts unpublished; publishing it to the AI caller is done in the app. Owners, admins and managers. `dry_run=true` answers it as it would be saved.\n\nRequires the `voice:write` scope (reaches people, spends or publishes).",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "voice:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "language": {
                    "type": "string",
                    "pattern": "^[a-z]{2}(?:[-_][A-Za-z]{2})?$",
                    "description": "A language code, e.g. sv, en, en-GB."
                  },
                  "first_message": {
                    "type": "string",
                    "maxLength": 1000
                  },
                  "script": {
                    "type": "string",
                    "maxLength": 20000
                  },
                  "voice_preset_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "phone_number_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "Nora — staffing",
                "language": "sv",
                "first_message": "Hej, det är Nora från Example Care.",
                "script": "You call nurses who asked about shifts…"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Create a voice agent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "voice_agent"
                    },
                    "name": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "language": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "first_message": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "script": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "What the agent is told to do on a call (its prompt)."
                    },
                    "voice_preset_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "phone_number_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "published": {
                      "type": "boolean",
                      "description": "Live with the AI caller. Publishing (and changing a published agent's voice or tools) is done in the app."
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updated_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "description",
                    "language",
                    "first_message",
                    "script",
                    "voice_preset_id",
                    "phone_number_id",
                    "published",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "One of the AI caller's agents."
                },
                "example": {
                  "id": "9c0d1e2f-3a4b-4c5d-8e6f-7a8b9c0d1e2f",
                  "object": "voice_agent",
                  "name": "Nora — staffing",
                  "description": "Books intro calls",
                  "language": "sv",
                  "first_message": "Hej, det är Nora från Example Care.",
                  "script": "You call nurses who asked about shifts…",
                  "voice_preset_id": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                  "phone_number_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "published": false,
                  "created_at": "2026-10-01T08:00:00.000Z",
                  "updated_at": "2026-11-05T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "voice:write",
        "x-norreach-action": "voice.agents",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/voice-agents/{id}": {
      "get": {
        "operationId": "get_voice_agent",
        "summary": "Get a voice agent",
        "description": "One of the AI caller's agents: its name, language, first message, script, voice and number, and whether it is published to the AI caller.\n\nRequires the `calls:read` scope.",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "calls:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a voice agent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "voice_agent"
                    },
                    "name": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "language": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "first_message": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "script": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "What the agent is told to do on a call (its prompt)."
                    },
                    "voice_preset_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "phone_number_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "published": {
                      "type": "boolean",
                      "description": "Live with the AI caller. Publishing (and changing a published agent's voice or tools) is done in the app."
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updated_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "description",
                    "language",
                    "first_message",
                    "script",
                    "voice_preset_id",
                    "phone_number_id",
                    "published",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "One of the AI caller's agents."
                },
                "example": {
                  "id": "9c0d1e2f-3a4b-4c5d-8e6f-7a8b9c0d1e2f",
                  "object": "voice_agent",
                  "name": "Nora — staffing",
                  "description": "Books intro calls",
                  "language": "sv",
                  "first_message": "Hej, det är Nora från Example Care.",
                  "script": "You call nurses who asked about shifts…",
                  "voice_preset_id": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                  "phone_number_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "published": true,
                  "created_at": "2026-10-01T08:00:00.000Z",
                  "updated_at": "2026-11-05T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "calls:read",
        "x-norreach-action": null,
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_voice_agent",
        "summary": "Change a voice agent",
        "description": "Changes an agent's name, description, language, first message, script, voice or number, as the app's agent editor saves it. A published agent's new script is used from its next call (as the app's edited scripts are); its voice and tools change when it is published again in the app. Owners, admins and managers. `dry_run=true` answers it as it would be.\n\nRequires the `voice:write` scope (reaches people, spends or publishes).",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "voice:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 500
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "language": {
                    "anyOf": [
                      {
                        "type": "string",
                        "pattern": "^[a-z]{2}(?:[-_][A-Za-z]{2})?$",
                        "description": "A language code, e.g. sv, en, en-GB."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "first_message": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 1000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "script": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 20000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "voice_preset_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "phone_number_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "description": "An id (UUID)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "first_message": "Hej! Nora här från Example Care."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Change a voice agent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "voice_agent"
                    },
                    "name": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "language": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "first_message": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "script": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "What the agent is told to do on a call (its prompt)."
                    },
                    "voice_preset_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "phone_number_id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "published": {
                      "type": "boolean",
                      "description": "Live with the AI caller. Publishing (and changing a published agent's voice or tools) is done in the app."
                    },
                    "created_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updated_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "description",
                    "language",
                    "first_message",
                    "script",
                    "voice_preset_id",
                    "phone_number_id",
                    "published",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false,
                  "description": "One of the AI caller's agents."
                },
                "example": {
                  "id": "9c0d1e2f-3a4b-4c5d-8e6f-7a8b9c0d1e2f",
                  "object": "voice_agent",
                  "name": "Nora — staffing",
                  "description": "Books intro calls",
                  "language": "sv",
                  "first_message": "Hej! Nora här från Example Care.",
                  "script": "You call nurses who asked about shifts…",
                  "voice_preset_id": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                  "phone_number_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
                  "published": true,
                  "created_at": "2026-10-01T08:00:00.000Z",
                  "updated_at": "2026-11-05T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "voice:write",
        "x-norreach-action": "voice.agents",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/voices": {
      "get": {
        "operationId": "list_voices",
        "summary": "List voices",
        "description": "The voices the workspace's agents can speak with: the defaults, the ones added from the library and the workspace's own cloned voices, with their tuning. Pass one as `voice_preset_id` to a voice agent. Cloning a voice is done in the app.\n\nRequires the `calls:read` scope.",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "calls:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List voices",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "voice"
                          },
                          "name": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "default",
                              "library",
                              "cloned"
                            ]
                          },
                          "latency_class": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "speed": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "stability": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "similarity": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "version": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "name",
                          "kind",
                          "latency_class",
                          "speed",
                          "stability",
                          "similarity",
                          "version"
                        ],
                        "additionalProperties": false,
                        "description": "A voice the workspace's agents can speak with (`voice_preset_id`)."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                      "object": "voice",
                      "name": "Warm Swedish",
                      "kind": "default",
                      "latency_class": "low",
                      "speed": 1,
                      "stability": 0.5,
                      "similarity": 0.75,
                      "version": 1
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "calls:read",
        "x-norreach-action": null,
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/webhook-deliveries/{id}": {
      "get": {
        "operationId": "get_webhook_delivery",
        "summary": "One delivery",
        "description": "A delivery: its status, attempts, your endpoint's answer and the exact body sent.\n\nRequires the `webhooks:read` scope.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "webhooks:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One delivery",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "webhook_delivery"
                    },
                    "endpoint_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "event_id": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "event_type": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "succeeded",
                        "failed",
                        "abandoned"
                      ]
                    },
                    "attempt": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "next_attempt_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "response_status": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "response_ms": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "response_excerpt": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The first 1 KB of your endpoint's answer."
                    },
                    "payload": {
                      "anyOf": [
                        {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The exact body sent (null until the first attempt)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "delivered_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "endpoint_id",
                    "event_id",
                    "event_type",
                    "status",
                    "attempt",
                    "next_attempt_at",
                    "response_status",
                    "response_ms",
                    "response_excerpt",
                    "payload",
                    "created_at",
                    "delivered_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                  "object": "webhook_delivery",
                  "endpoint_id": "0f1a2b3c-4d5e-4f6a-8b7c-9d0e1f2a3b4c",
                  "event_id": "evt_48213",
                  "event_type": "lead.submitted",
                  "status": "succeeded",
                  "attempt": 1,
                  "next_attempt_at": null,
                  "response_status": 200,
                  "response_ms": 182,
                  "response_excerpt": "ok",
                  "payload": {
                    "id": "evt_48213",
                    "object": "event",
                    "type": "lead.submitted"
                  },
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "delivered_at": "2026-11-04T09:12:34.004Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "webhooks:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/webhook-deliveries/{id}/redeliver": {
      "post": {
        "operationId": "redeliver_webhook",
        "summary": "Send a delivery again",
        "description": "Queues the same event (the same body, a new delivery id) to its endpoint again.\n\nRequires the `webhooks:write` scope.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "webhooks:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Send a delivery again",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "webhook_delivery"
                    },
                    "endpoint_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "event_id": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "event_type": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "succeeded",
                        "failed",
                        "abandoned"
                      ]
                    },
                    "attempt": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "next_attempt_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "response_status": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "response_ms": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "response_excerpt": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The first 1 KB of your endpoint's answer."
                    },
                    "payload": {
                      "anyOf": [
                        {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The exact body sent (null until the first attempt)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "delivered_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "endpoint_id",
                    "event_id",
                    "event_type",
                    "status",
                    "attempt",
                    "next_attempt_at",
                    "response_status",
                    "response_ms",
                    "response_excerpt",
                    "payload",
                    "created_at",
                    "delivered_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
                  "object": "webhook_delivery",
                  "endpoint_id": "0f1a2b3c-4d5e-4f6a-8b7c-9d0e1f2a3b4c",
                  "event_id": "evt_48213",
                  "event_type": "lead.submitted",
                  "status": "pending",
                  "attempt": 0,
                  "next_attempt_at": "2026-11-04T10:00:00.000Z",
                  "response_status": 200,
                  "response_ms": 182,
                  "response_excerpt": "ok",
                  "payload": {
                    "id": "evt_48213",
                    "object": "event",
                    "type": "lead.submitted"
                  },
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "delivered_at": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "webhooks:write",
        "x-norreach-action": "api.keys",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/webhook-endpoints": {
      "get": {
        "operationId": "list_webhook_endpoints",
        "summary": "List webhook endpoints",
        "description": "The workspace's webhook endpoints (at most 10).\n\nRequires the `webhooks:read` scope.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "webhooks:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List webhook endpoints",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "webhook_endpoint"
                          },
                          "url": {
                            "type": "string"
                          },
                          "description": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "event_types": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "disabled",
                              "paused"
                            ],
                            "description": "paused = the person who made it left; an admin takes it over in Settings."
                          },
                          "include_content": {
                            "type": "boolean",
                            "description": "Message events carry the subject and text."
                          },
                          "disabled_reason": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "by_user, gone (the endpoint answered 410), failing, creator_inactive."
                          },
                          "created_by": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "description": "An id (UUID)."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "created_via_key": {
                            "type": "boolean"
                          },
                          "previous_secret_valid_until": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "After a rotation the old secret also signs until then."
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "updated_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "url",
                          "description",
                          "event_types",
                          "status",
                          "include_content",
                          "disabled_reason",
                          "created_by",
                          "created_via_key",
                          "previous_secret_valid_until",
                          "created_at",
                          "updated_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "0f1a2b3c-4d5e-4f6a-8b7c-9d0e1f2a3b4c",
                      "object": "webhook_endpoint",
                      "url": "https://hooks.example.com/norreach",
                      "description": "CRM sync",
                      "event_types": [
                        "lead.submitted",
                        "contact.created"
                      ],
                      "status": "active",
                      "include_content": false,
                      "disabled_reason": null,
                      "created_by": "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00",
                      "created_via_key": true,
                      "previous_secret_valid_until": null,
                      "created_at": "2026-11-04T09:12:33.120Z",
                      "updated_at": "2026-11-04T09:12:33.120Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "webhooks:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "create_webhook_endpoint",
        "summary": "Add a webhook endpoint",
        "description": "Sends the chosen events to your URL, signed. The answer includes the signing `secret` — the only time it is shown. You can subscribe only to events this key's scopes may read (e.g. `lead.submitted` needs pages:read). Workspace admins are told when an endpoint is added.\n\nRequires the `webhooks:write` scope.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "webhooks:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "maxLength": 2048,
                    "description": "A public https:// address on port 443."
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 500
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "event_types": {
                    "minItems": 1,
                    "maxItems": 40,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "contact.created",
                        "contact.tag_added",
                        "contact.tag_removed",
                        "list.member_added",
                        "list.member_removed",
                        "consent.updated",
                        "contact.unsubscribed",
                        "deal.stage_changed",
                        "lead.submitted",
                        "ad_lead.received",
                        "message.received",
                        "message.sent",
                        "message.delivered",
                        "message.opened",
                        "message.clicked",
                        "message.bounced",
                        "message.blocked",
                        "message.failed",
                        "call.started",
                        "call.completed",
                        "meeting.booked",
                        "meeting.rescheduled",
                        "meeting.cancelled",
                        "meeting.requested",
                        "enrollment.created",
                        "enrollment.completed",
                        "enrollment.replied",
                        "enrollment.exited",
                        "enrollment.paused",
                        "approval.requested",
                        "page.published",
                        "page.unpublished",
                        "plan.generated",
                        "post.published",
                        "post.failed",
                        "number.purchased",
                        "ad_campaign.paused",
                        "ad_campaign.resumed",
                        "template.status_changed",
                        "ping"
                      ]
                    }
                  },
                  "include_content": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "url",
                  "event_types"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://hooks.example.com/norreach",
                "event_types": [
                  "lead.submitted",
                  "contact.created"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Add a webhook endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "webhook_endpoint"
                    },
                    "url": {
                      "type": "string"
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "event_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "disabled",
                        "paused"
                      ],
                      "description": "paused = the person who made it left; an admin takes it over in Settings."
                    },
                    "include_content": {
                      "type": "boolean",
                      "description": "Message events carry the subject and text."
                    },
                    "disabled_reason": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "by_user, gone (the endpoint answered 410), failing, creator_inactive."
                    },
                    "created_by": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_via_key": {
                      "type": "boolean"
                    },
                    "previous_secret_valid_until": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "After a rotation the old secret also signs until then."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "secret": {
                      "type": "string",
                      "description": "The signing secret — shown only now. Store it; NorReach keeps only an encrypted copy."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "url",
                    "description",
                    "event_types",
                    "status",
                    "include_content",
                    "disabled_reason",
                    "created_by",
                    "created_via_key",
                    "previous_secret_valid_until",
                    "created_at",
                    "updated_at",
                    "secret"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "0f1a2b3c-4d5e-4f6a-8b7c-9d0e1f2a3b4c",
                  "object": "webhook_endpoint",
                  "url": "https://hooks.example.com/norreach",
                  "description": "CRM sync",
                  "event_types": [
                    "lead.submitted",
                    "contact.created"
                  ],
                  "status": "active",
                  "include_content": false,
                  "disabled_reason": null,
                  "created_by": "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00",
                  "created_via_key": true,
                  "previous_secret_valid_until": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T09:12:33.120Z",
                  "secret": "whsec_9x2…"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "webhooks:write",
        "x-norreach-action": "api.keys",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/webhook-endpoints/{id}": {
      "delete": {
        "operationId": "delete_webhook_endpoint",
        "summary": "Remove a webhook endpoint",
        "description": "Stops all deliveries to it and removes its delivery log.\n\nRequires the `webhooks:write` scope.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "webhooks:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Remove a webhook endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "webhook_endpoint"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "deleted"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "0f1a2b3c-4d5e-4f6a-8b7c-9d0e1f2a3b4c",
                  "object": "webhook_endpoint",
                  "deleted": true
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "webhooks:write",
        "x-norreach-action": "api.keys",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "get": {
        "operationId": "get_webhook_endpoint",
        "summary": "One webhook endpoint",
        "description": "A webhook endpoint (never its secret).\n\nRequires the `webhooks:read` scope.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "webhooks:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One webhook endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "webhook_endpoint"
                    },
                    "url": {
                      "type": "string"
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "event_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "disabled",
                        "paused"
                      ],
                      "description": "paused = the person who made it left; an admin takes it over in Settings."
                    },
                    "include_content": {
                      "type": "boolean",
                      "description": "Message events carry the subject and text."
                    },
                    "disabled_reason": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "by_user, gone (the endpoint answered 410), failing, creator_inactive."
                    },
                    "created_by": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_via_key": {
                      "type": "boolean"
                    },
                    "previous_secret_valid_until": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "After a rotation the old secret also signs until then."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "url",
                    "description",
                    "event_types",
                    "status",
                    "include_content",
                    "disabled_reason",
                    "created_by",
                    "created_via_key",
                    "previous_secret_valid_until",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "0f1a2b3c-4d5e-4f6a-8b7c-9d0e1f2a3b4c",
                  "object": "webhook_endpoint",
                  "url": "https://hooks.example.com/norreach",
                  "description": "CRM sync",
                  "event_types": [
                    "lead.submitted",
                    "contact.created"
                  ],
                  "status": "active",
                  "include_content": false,
                  "disabled_reason": null,
                  "created_by": "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00",
                  "created_via_key": true,
                  "previous_secret_valid_until": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "webhooks:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_webhook_endpoint",
        "summary": "Change a webhook endpoint",
        "description": "URL, description, events, include_content, or `status` (active / disabled). Turning a disabled endpoint back on resets its failure count.\n\nRequires the `webhooks:write` scope.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "webhooks:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "maxLength": 2048,
                    "description": "A public https:// address on port 443."
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 500
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "event_types": {
                    "minItems": 1,
                    "maxItems": 40,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "contact.created",
                        "contact.tag_added",
                        "contact.tag_removed",
                        "list.member_added",
                        "list.member_removed",
                        "consent.updated",
                        "contact.unsubscribed",
                        "deal.stage_changed",
                        "lead.submitted",
                        "ad_lead.received",
                        "message.received",
                        "message.sent",
                        "message.delivered",
                        "message.opened",
                        "message.clicked",
                        "message.bounced",
                        "message.blocked",
                        "message.failed",
                        "call.started",
                        "call.completed",
                        "meeting.booked",
                        "meeting.rescheduled",
                        "meeting.cancelled",
                        "meeting.requested",
                        "enrollment.created",
                        "enrollment.completed",
                        "enrollment.replied",
                        "enrollment.exited",
                        "enrollment.paused",
                        "approval.requested",
                        "page.published",
                        "page.unpublished",
                        "plan.generated",
                        "post.published",
                        "post.failed",
                        "number.purchased",
                        "ad_campaign.paused",
                        "ad_campaign.resumed",
                        "template.status_changed",
                        "ping"
                      ]
                    }
                  },
                  "include_content": {
                    "type": "boolean"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "disabled"
                    ]
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "status": "disabled"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Change a webhook endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "webhook_endpoint"
                    },
                    "url": {
                      "type": "string"
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "event_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "disabled",
                        "paused"
                      ],
                      "description": "paused = the person who made it left; an admin takes it over in Settings."
                    },
                    "include_content": {
                      "type": "boolean",
                      "description": "Message events carry the subject and text."
                    },
                    "disabled_reason": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "by_user, gone (the endpoint answered 410), failing, creator_inactive."
                    },
                    "created_by": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_via_key": {
                      "type": "boolean"
                    },
                    "previous_secret_valid_until": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "After a rotation the old secret also signs until then."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "url",
                    "description",
                    "event_types",
                    "status",
                    "include_content",
                    "disabled_reason",
                    "created_by",
                    "created_via_key",
                    "previous_secret_valid_until",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "0f1a2b3c-4d5e-4f6a-8b7c-9d0e1f2a3b4c",
                  "object": "webhook_endpoint",
                  "url": "https://hooks.example.com/norreach",
                  "description": "CRM sync",
                  "event_types": [
                    "lead.submitted",
                    "contact.created"
                  ],
                  "status": "disabled",
                  "include_content": false,
                  "disabled_reason": "by_user",
                  "created_by": "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00",
                  "created_via_key": true,
                  "previous_secret_valid_until": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T09:12:33.120Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "webhooks:write",
        "x-norreach-action": "api.keys",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/webhook-endpoints/{id}/deliveries": {
      "get": {
        "operationId": "list_webhook_deliveries",
        "summary": "An endpoint's deliveries",
        "description": "The delivery log, newest first (kept 30 days): status, attempts, your endpoint's answer and the exact body sent.\n\nRequires the `webhooks:read` scope.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "webhooks:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (1–200, default 50).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "succeeded",
                "failed",
                "abandoned"
              ]
            }
          },
          {
            "name": "event_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 60
            }
          }
        ],
        "responses": {
          "200": {
            "description": "An endpoint's deliveries",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "webhook_delivery"
                          },
                          "endpoint_id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "event_id": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "event_type": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "succeeded",
                              "failed",
                              "abandoned"
                            ]
                          },
                          "attempt": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "next_attempt_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "response_status": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "response_ms": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "response_excerpt": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The first 1 KB of your endpoint's answer."
                          },
                          "payload": {
                            "anyOf": [
                              {
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {}
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "The exact body sent (null until the first attempt)."
                          },
                          "created_at": {
                            "type": "string",
                            "description": "RFC 3339 UTC timestamp with milliseconds."
                          },
                          "delivered_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "endpoint_id",
                          "event_id",
                          "event_type",
                          "status",
                          "attempt",
                          "next_attempt_at",
                          "response_status",
                          "response_ms",
                          "response_excerpt",
                          "payload",
                          "created_at",
                          "delivered_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                      "object": "webhook_delivery",
                      "endpoint_id": "0f1a2b3c-4d5e-4f6a-8b7c-9d0e1f2a3b4c",
                      "event_id": "evt_48213",
                      "event_type": "lead.submitted",
                      "status": "succeeded",
                      "attempt": 1,
                      "next_attempt_at": null,
                      "response_status": 200,
                      "response_ms": 182,
                      "response_excerpt": "ok",
                      "payload": {
                        "id": "evt_48213",
                        "object": "event",
                        "type": "lead.submitted"
                      },
                      "created_at": "2026-11-04T09:12:33.120Z",
                      "delivered_at": "2026-11-04T09:12:34.004Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `invalid_cursor` — That cursor doesn't belong to this list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "webhooks:read",
        "x-norreach-action": null,
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/webhook-endpoints/{id}/rotate-secret": {
      "post": {
        "operationId": "rotate_webhook_secret",
        "summary": "Rotate the signing secret",
        "description": "A new signing secret, shown once. For 24 hours deliveries carry a signature with the old secret too, so you can switch without missing events.\n\nRequires the `webhooks:write` scope.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "webhooks:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rotate the signing secret",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "webhook_endpoint"
                    },
                    "url": {
                      "type": "string"
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "event_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "disabled",
                        "paused"
                      ],
                      "description": "paused = the person who made it left; an admin takes it over in Settings."
                    },
                    "include_content": {
                      "type": "boolean",
                      "description": "Message events carry the subject and text."
                    },
                    "disabled_reason": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "by_user, gone (the endpoint answered 410), failing, creator_inactive."
                    },
                    "created_by": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "description": "An id (UUID)."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created_via_key": {
                      "type": "boolean"
                    },
                    "previous_secret_valid_until": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "After a rotation the old secret also signs until then."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "secret": {
                      "type": "string",
                      "description": "The signing secret — shown only now. Store it; NorReach keeps only an encrypted copy."
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "url",
                    "description",
                    "event_types",
                    "status",
                    "include_content",
                    "disabled_reason",
                    "created_by",
                    "created_via_key",
                    "previous_secret_valid_until",
                    "created_at",
                    "updated_at",
                    "secret"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "0f1a2b3c-4d5e-4f6a-8b7c-9d0e1f2a3b4c",
                  "object": "webhook_endpoint",
                  "url": "https://hooks.example.com/norreach",
                  "description": "CRM sync",
                  "event_types": [
                    "lead.submitted",
                    "contact.created"
                  ],
                  "status": "active",
                  "include_content": false,
                  "disabled_reason": null,
                  "created_by": "0b6f8a52-8d9e-4c1a-b7f3-5e2d9c4a1b00",
                  "created_via_key": true,
                  "previous_secret_valid_until": "2026-11-05T09:12:33.120Z",
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "updated_at": "2026-11-04T09:12:33.120Z",
                  "secret": "whsec_k3…"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "webhooks:write",
        "x-norreach-action": "api.keys",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/webhook-endpoints/{id}/test": {
      "post": {
        "operationId": "test_webhook_endpoint",
        "summary": "Send a test event",
        "description": "Queues a signed `ping` event to the endpoint (it arrives within a minute). Follow it with GET /webhook-deliveries/{id}.\n\nRequires the `webhooks:write` scope.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "webhooks:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "An id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Send a test event",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "webhook_delivery"
                    },
                    "endpoint_id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "event_id": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "event_type": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "succeeded",
                        "failed",
                        "abandoned"
                      ]
                    },
                    "attempt": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "next_attempt_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "response_status": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "response_ms": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "response_excerpt": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The first 1 KB of your endpoint's answer."
                    },
                    "payload": {
                      "anyOf": [
                        {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The exact body sent (null until the first attempt)."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "RFC 3339 UTC timestamp with milliseconds."
                    },
                    "delivered_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "endpoint_id",
                    "event_id",
                    "event_type",
                    "status",
                    "attempt",
                    "next_attempt_at",
                    "response_status",
                    "response_ms",
                    "response_excerpt",
                    "payload",
                    "created_at",
                    "delivered_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                  "object": "webhook_delivery",
                  "endpoint_id": "0f1a2b3c-4d5e-4f6a-8b7c-9d0e1f2a3b4c",
                  "event_id": null,
                  "event_type": "ping",
                  "status": "pending",
                  "attempt": 0,
                  "next_attempt_at": "2026-11-04T09:12:33.120Z",
                  "response_status": null,
                  "response_ms": null,
                  "response_excerpt": null,
                  "payload": null,
                  "created_at": "2026-11-04T09:12:33.120Z",
                  "delivered_at": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — That doesn't exist.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "webhooks:write",
        "x-norreach-action": "api.keys",
        "x-norreach-phase": "A",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      }
    },
    "/whatsapp-templates": {
      "get": {
        "operationId": "list_whatsapp_templates",
        "summary": "List WhatsApp templates",
        "description": "The workspace's WhatsApp templates as last synced: name, language, category, WhatsApp's review state (`status` — only APPROVED templates can be sent, POST /messages `template`), why one was rejected, its quality and its body. Filter by `status`. POST /whatsapp-templates/sync reads the review states again.\n\nRequires the `templates:read` scope.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "templates:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z_]{2,20}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List WhatsApp templates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "An id (UUID)."
                          },
                          "object": {
                            "type": "string",
                            "const": "whatsapp_template"
                          },
                          "name": {
                            "type": "string"
                          },
                          "language": {
                            "type": "string"
                          },
                          "category": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "WhatsApp's review state: PENDING, APPROVED, REJECTED, PAUSED, DISABLED … — only APPROVED templates can be sent."
                          },
                          "rejection_reason": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "quality_score": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "body": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "variable_count": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "synced_at": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "RFC 3339 UTC timestamp with milliseconds."
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "object",
                          "name",
                          "language",
                          "category",
                          "status",
                          "rejection_reason",
                          "quality_score",
                          "body",
                          "variable_count",
                          "synced_at"
                        ],
                        "additionalProperties": false,
                        "description": "A WhatsApp template of the workspace's business account."
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "6f7a8b9c-0d1e-4f2a-9b3c-4d5e6f7a8b9c",
                      "object": "whatsapp_template",
                      "name": "follow_up",
                      "language": "sv",
                      "category": "MARKETING",
                      "status": "APPROVED",
                      "rejection_reason": null,
                      "quality_score": "GREEN",
                      "body": "Hej {{1}}, har du tid för ett samtal?",
                      "variable_count": 1,
                      "synced_at": "2026-11-05T08:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "templates:read",
        "x-norreach-action": null,
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "post": {
        "operationId": "create_whatsapp_template",
        "summary": "Submit a WhatsApp template for review",
        "description": "Writes a WhatsApp template (your own words — a body with {{1}}, {{2}} … variables and one example each) and sends it to WhatsApp for review under the workspace's own business account, exactly as Campaigns › Templates does: the same checks (name, category MARKETING or UTILITY, a language from the app's list, at most 1024 characters and 10 variables), and a name + language can exist once (409). It starts PENDING; the verdict arrives with a sync (template.status_changed). Owners, admins and managers. 409 no_sender while no business account is connected. Idempotency-Key required; `dry_run=true` checks everything and sends nothing.\n\nRequires the `templates:write` scope.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "templates:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512,
                    "description": "Lowercase letters, digits and underscores."
                  },
                  "category": {
                    "type": "string",
                    "enum": [
                      "MARKETING",
                      "UTILITY"
                    ]
                  },
                  "language": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 10,
                    "description": "A language code from the app's list, e.g. en_US, sv."
                  },
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 1024,
                    "description": "The message, with {{1}}, {{2}} … for variables (numbered from 1, no gaps; not at the very start or end)."
                  },
                  "examples": {
                    "default": [],
                    "description": "One example value per variable, in order.",
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 200
                    }
                  }
                },
                "required": [
                  "name",
                  "category",
                  "language",
                  "body"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "follow_up",
                "category": "MARKETING",
                "language": "sv",
                "body": "Hej {{1}}, har du tid för ett samtal?",
                "examples": [
                  "Anna"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Submit a WhatsApp template for review",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "whatsapp_template_action"
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "submit",
                        "sync"
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "synced": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "template": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            "object": {
                              "type": "string",
                              "const": "whatsapp_template"
                            },
                            "name": {
                              "type": "string"
                            },
                            "language": {
                              "type": "string"
                            },
                            "category": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "status": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "WhatsApp's review state: PENDING, APPROVED, REJECTED, PAUSED, DISABLED … — only APPROVED templates can be sent."
                            },
                            "rejection_reason": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "quality_score": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "body": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "variable_count": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "synced_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "id",
                            "object",
                            "name",
                            "language",
                            "category",
                            "status",
                            "rejection_reason",
                            "quality_score",
                            "body",
                            "variable_count",
                            "synced_at"
                          ],
                          "additionalProperties": false,
                          "description": "A WhatsApp template of the workspace's business account."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "action",
                    "dry_run",
                    "synced",
                    "template",
                    "note"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "whatsapp_template_action",
                  "action": "submit",
                  "dry_run": false,
                  "synced": null,
                  "template": {
                    "id": "6f7a8b9c-0d1e-4f2a-9b3c-4d5e6f7a8b9c",
                    "object": "whatsapp_template",
                    "name": "follow_up",
                    "language": "sv",
                    "category": "MARKETING",
                    "status": "PENDING",
                    "rejection_reason": null,
                    "quality_score": null,
                    "body": "Hej {{1}}, har du tid för ett samtal?",
                    "variable_count": 1,
                    "synced_at": "2026-11-05T08:00:00.000Z"
                  },
                  "note": "Template “follow_up” submitted — WhatsApp reviews it before it can be sent."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state. · `no_sender` — A channel this needs has no connected sender.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "templates:write",
        "x-norreach-action": "channels.templates",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/whatsapp-templates/sync": {
      "post": {
        "operationId": "sync_whatsapp_templates",
        "summary": "Sync WhatsApp templates",
        "description": "Reads the workspace's templates and their review states from WhatsApp again (the Sync button of Campaigns › Templates). Every changed review state fires template.status_changed. Owners, admins and managers. `dry_run=true` changes nothing.\n\nRequires the `templates:write` scope.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "templates:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sync WhatsApp templates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "whatsapp_template_action"
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "submit",
                        "sync"
                      ]
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "synced": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "template": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "description": "An id (UUID)."
                            },
                            "object": {
                              "type": "string",
                              "const": "whatsapp_template"
                            },
                            "name": {
                              "type": "string"
                            },
                            "language": {
                              "type": "string"
                            },
                            "category": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "status": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "WhatsApp's review state: PENDING, APPROVED, REJECTED, PAUSED, DISABLED … — only APPROVED templates can be sent."
                            },
                            "rejection_reason": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "quality_score": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "body": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "variable_count": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "synced_at": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "RFC 3339 UTC timestamp with milliseconds."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "id",
                            "object",
                            "name",
                            "language",
                            "category",
                            "status",
                            "rejection_reason",
                            "quality_score",
                            "body",
                            "variable_count",
                            "synced_at"
                          ],
                          "additionalProperties": false,
                          "description": "A WhatsApp template of the workspace's business account."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "action",
                    "dry_run",
                    "synced",
                    "template",
                    "note"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "whatsapp_template_action",
                  "action": "sync",
                  "dry_run": false,
                  "synced": 12,
                  "template": null,
                  "note": "Templates synced."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "templates:write",
        "x-norreach-action": "channels.templates",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/workspace": {
      "get": {
        "operationId": "get_workspace",
        "summary": "The workspace",
        "description": "The workspace this key belongs to: its name, time zone, the countries it texts and calls, and whether all outreach is paused (when, and by whom).\n\nRequires the `workspace:read` scope.",
        "tags": [
          "Workspace"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "workspace:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "The workspace",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "workspace"
                    },
                    "name": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "timezone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The booking page's time zone, when one is set up."
                    },
                    "countries": {
                      "type": "object",
                      "properties": {
                        "texts": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Countries the workspace texts (ISO 3166-1 alpha-2)."
                        },
                        "calls": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Countries the workspace calls."
                        }
                      },
                      "required": [
                        "texts",
                        "calls"
                      ],
                      "additionalProperties": false
                    },
                    "outreach": {
                      "type": "object",
                      "properties": {
                        "paused": {
                          "type": "boolean"
                        },
                        "paused_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "paused_by": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "The name of who paused it."
                        }
                      },
                      "required": [
                        "paused",
                        "paused_at",
                        "paused_by"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "timezone",
                    "countries",
                    "outreach"
                  ],
                  "additionalProperties": false,
                  "description": "The workspace this key belongs to."
                },
                "example": {
                  "id": "5c3e2a10-9b8d-4f6e-a1c2-3d4e5f6a7b8c",
                  "object": "workspace",
                  "name": "Acme Staffing",
                  "timezone": "Europe/Stockholm",
                  "countries": {
                    "texts": [
                      "SE"
                    ],
                    "calls": [
                      "NO",
                      "SE"
                    ]
                  },
                  "outreach": {
                    "paused": false,
                    "paused_at": null,
                    "paused_by": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "workspace:read",
        "x-norreach-action": null,
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "none",
        "x-norreach-dry-run": false,
        "x-norreach-reaches-people": false
      },
      "patch": {
        "operationId": "update_workspace",
        "summary": "Change the workspace's settings",
        "description": "Changes the workspace's name, company name and time zone (the booking pages' and the workspace's default — set up booking once in the app first, 409 otherwise). There is no workspace language: each person picks theirs. Deleting the workspace, moving ownership and billing are done in the app only. Owners and admins. `dry_run=true` answers it as it would be.\n\nRequires the `workspace:settings` scope.",
        "tags": [
          "Workspace"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "workspace:settings"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "company_name": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "timezone": {
                    "description": "An IANA time zone, e.g. Europe/Stockholm — the booking pages' and the workspace's default.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "name": "Acme Staffing Nordic",
                "timezone": "Europe/Stockholm"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Change the workspace's settings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "An id (UUID)."
                    },
                    "object": {
                      "type": "string",
                      "const": "workspace"
                    },
                    "name": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "timezone": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "The booking page's time zone, when one is set up."
                    },
                    "countries": {
                      "type": "object",
                      "properties": {
                        "texts": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Countries the workspace texts (ISO 3166-1 alpha-2)."
                        },
                        "calls": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Countries the workspace calls."
                        }
                      },
                      "required": [
                        "texts",
                        "calls"
                      ],
                      "additionalProperties": false
                    },
                    "outreach": {
                      "type": "object",
                      "properties": {
                        "paused": {
                          "type": "boolean"
                        },
                        "paused_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "RFC 3339 UTC timestamp with milliseconds."
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "paused_by": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "The name of who paused it."
                        }
                      },
                      "required": [
                        "paused",
                        "paused_at",
                        "paused_by"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "name",
                    "timezone",
                    "countries",
                    "outreach"
                  ],
                  "additionalProperties": false,
                  "description": "The workspace this key belongs to."
                },
                "example": {
                  "id": "5c3e2a10-9b8d-4f6e-a1c2-3d4e5f6a7b8c",
                  "object": "workspace",
                  "name": "Acme Staffing Nordic",
                  "timezone": "Europe/Stockholm",
                  "countries": {
                    "texts": [
                      "SE"
                    ],
                    "calls": [
                      "SE"
                    ]
                  },
                  "outreach": {
                    "paused": false,
                    "paused_at": null,
                    "paused_by": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running. · `conflict` — That conflicts with the current state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "workspace:settings",
        "x-norreach-action": "settings.workspace",
        "x-norreach-phase": "D",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/workspace/outreach/pause": {
      "post": {
        "operationId": "pause_outreach",
        "summary": "Pause all outreach",
        "description": "The brake: every running campaign and automation is paused and queued messages are cancelled, and nothing reaches anyone (no email, text, WhatsApp, LinkedIn step or AI call) until it's resumed — in the app or with /resume. Works while already paused (anything that slipped in is stopped too). Owners, admins and managers.\n\nRequires the `workspace:admin` scope (reaches people, spends or publishes).",
        "tags": [
          "Workspace"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "workspace:admin"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pause all outreach",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "outreach_pause"
                    },
                    "paused": {
                      "type": "boolean"
                    },
                    "paused_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "paused_by": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "campaigns_paused": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Pause: running campaigns and automations it paused (a dry run: would pause)."
                    },
                    "messages_canceled": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Pause: queued messages it cancelled (a dry run: would cancel)."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "paused",
                    "paused_at",
                    "paused_by",
                    "changed",
                    "dry_run",
                    "campaigns_paused",
                    "messages_canceled",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "Outreach for the whole workspace, after a pause or resume."
                },
                "example": {
                  "object": "outreach_pause",
                  "paused": true,
                  "paused_at": "2026-11-05T10:00:00.000Z",
                  "paused_by": "Alex Andersson",
                  "changed": true,
                  "dry_run": false,
                  "campaigns_paused": 3,
                  "messages_canceled": 41,
                  "note": "All outreach is paused. Nothing goes out until it's resumed."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "workspace:admin",
        "x-norreach-action": "outreach.pause",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "optional",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    },
    "/workspace/outreach/resume": {
      "post": {
        "operationId": "resume_outreach",
        "summary": "Resume outreach",
        "description": "Lifts the pause: sending is allowed again. Nothing the pause stopped restarts by itself — resume campaigns and automations one by one. Owners, admins and managers.\n\nRequires the `workspace:admin` scope (reaches people, spends or publishes).",
        "tags": [
          "Workspace"
        ],
        "security": [
          {
            "bearerAuth": []
          },
          {
            "oauth2": [
              "workspace:admin"
            ]
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "description": "Run every check and return what would happen, changing nothing.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resume outreach",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "outreach_pause"
                    },
                    "paused": {
                      "type": "boolean"
                    },
                    "paused_at": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "RFC 3339 UTC timestamp with milliseconds."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "paused_by": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "dry_run": {
                      "type": "boolean"
                    },
                    "campaigns_paused": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Pause: running campaigns and automations it paused (a dry run: would pause)."
                    },
                    "messages_canceled": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Pause: queued messages it cancelled (a dry run: would cancel)."
                    },
                    "note": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "paused",
                    "paused_at",
                    "paused_by",
                    "changed",
                    "dry_run",
                    "campaigns_paused",
                    "messages_canceled",
                    "note"
                  ],
                  "additionalProperties": false,
                  "description": "Outreach for the whole workspace, after a pause or resume."
                },
                "example": {
                  "object": "outreach_pause",
                  "paused": false,
                  "paused_at": null,
                  "paused_by": null,
                  "changed": true,
                  "dry_run": false,
                  "campaigns_paused": 0,
                  "messages_canceled": 0,
                  "note": "Outreach is on again. Campaigns the pause stopped stay paused until you resume them."
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — The request couldn't be read. · `unknown_field` — The request has a field this operation doesn't know. · `idempotency_key_required` — This operation needs an Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — A valid API key is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — This API key doesn't have the scope this operation needs. · `feature_not_enabled` — The API isn't switched on for this workspace. · `role_forbidden` — The key's creator's role can't do this.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_in_progress` — A request with this Idempotency-Key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`too_large` — The request body is too large.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed` — The request has invalid fields. · `idempotency_mismatch` — This Idempotency-Key was used with a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Slow down and try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`server_error` — Something went wrong on our side.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable` — The API isn't available right now. Try again shortly.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-norreach-scope": "workspace:admin",
        "x-norreach-action": "outreach.resume",
        "x-norreach-phase": "B",
        "x-norreach-idempotency": "required",
        "x-norreach-dry-run": true,
        "x-norreach-reaches-people": false
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key: `Authorization: Bearer nr_live_…`. Scopes: workspace:read, contacts:read, contacts:write, contacts:export, contacts:delete, suppressions:write, campaigns:read, campaigns:write, campaigns:launch, plans:read, plans:write, plans:approve, approvals:read, approvals:decide, inbox:read, messages:send, calls:read, calls:recordings, calls:place, meetings:read, meetings:write, deals:write, pages:read, pages:write, pages:publish, pages:domains, ads:read, ads:spend, social:read, social:publish, nora:ask, nora:run, nora:autonomy, analytics:read, billing:read, team:read, team:write, team:admin, workspace:admin, webhooks:read, webhooks:write, audit:read, numbers:read, numbers:verify, numbers:buy, templates:read, templates:write, voice:write, calls:routing, team:schedules, team:requests, workspace:settings, ads:limits."
      },
      "oauth2": {
        "type": "oauth2",
        "description": "An app connected with OAuth 2.1 (authorization code + PKCE S256, resource indicator https://api.norreach.app/v1). The token acts as the person who allowed it: `Authorization: Bearer nr_oat_…`, 1 hour; refresh tokens rotate.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://www.norreach.app/oauth/authorize",
            "tokenUrl": "https://api.norreach.app/oauth/token",
            "refreshUrl": "https://api.norreach.app/oauth/token",
            "scopes": {
              "workspace:read": "See the workspace, its senders and async jobs",
              "contacts:read": "Read contacts, lists, tags and do-not-contact entries",
              "contacts:write": "Create and update contacts, notes, tags, lists and consent",
              "contacts:export": "Export contacts and leads in bulk",
              "contacts:delete": "Erase a person's data (keeps a do-not-contact entry) (reaches people, spends or publishes)",
              "suppressions:write": "Add people and domains to do-not-contact (reaches people, spends or publishes)",
              "campaigns:read": "Read campaigns, sequences, automations and enrollments",
              "campaigns:write": "Create and edit campaigns and automations",
              "campaigns:launch": "Launch, pause and resume campaigns; enroll contacts (reaches people, spends or publishes)",
              "plans:read": "Read plans, briefs and cards",
              "plans:write": "File briefs, edit cards and ask for replans",
              "plans:approve": "Approve or skip plan cards; start and pause plans (reaches people, spends or publishes)",
              "approvals:read": "See the Approvals queue",
              "approvals:decide": "Approve or skip anything in the Approvals queue (reaches people, spends or publishes)",
              "inbox:read": "Read inbox threads and messages",
              "messages:send": "Send messages and replies (reaches people, spends or publishes)",
              "calls:read": "Read calls, outcomes and summaries",
              "calls:recordings": "Read call transcripts and recordings",
              "calls:place": "Request AI calls to saved contacts (reaches people, spends or publishes)",
              "meetings:read": "Read meetings, booking pages and availability",
              "meetings:write": "Book, approve and decline meetings",
              "deals:write": "Move deals between stages",
              "pages:read": "Read landing pages, versions, leads and analytics",
              "pages:write": "Edit landing page drafts and site settings",
              "pages:publish": "Publish and unpublish landing pages (reaches people, spends or publishes)",
              "pages:domains": "Add and manage custom domains",
              "ads:read": "Read ad accounts, launches and results",
              "ads:spend": "Publish Nora's ad launches and manage live ads (reaches people, spends or publishes)",
              "social:read": "Read social posts and connected profiles",
              "social:publish": "Create and schedule social posts (reaches people, spends or publishes)",
              "nora:ask": "Ask Nora questions",
              "nora:run": "Give Nora work to do (reaches people, spends or publishes)",
              "nora:autonomy": "Change what Nora may do without asking",
              "analytics:read": "Read dashboards and analytics",
              "billing:read": "See credits, usage and prices",
              "team:read": "See members and invites",
              "team:write": "Invite people to the workspace",
              "team:admin": "Change roles and switch people off (reaches people, spends or publishes)",
              "workspace:admin": "Pause and resume all outreach; compliance settings (reaches people, spends or publishes)",
              "webhooks:read": "See webhook endpoints and deliveries",
              "webhooks:write": "Add, change and test webhook endpoints",
              "audit:read": "Read the audit log",
              "numbers:read": "See phone numbers, numbers to buy and business verifications",
              "numbers:verify": "Submit business verification for phone numbers (reaches people, spends or publishes)",
              "numbers:buy": "Buy phone numbers — within the daily cap, waiting in Approvals unless an owner switched that off (reaches people, spends or publishes)",
              "templates:read": "Read message and WhatsApp templates",
              "templates:write": "Write message templates and send WhatsApp templates for review",
              "voice:write": "Create and change voice agents (reaches people, spends or publishes)",
              "calls:routing": "Change who answers incoming calls (reaches people, spends or publishes)",
              "team:schedules": "Set people's working hours and availability",
              "team:requests": "Read and handle the team's requests",
              "workspace:settings": "Change the workspace's name and time zone",
              "ads:limits": "Change ad accounts' spending limits (reaches people, spends or publishes)"
            }
          }
        }
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "A URL identifying the problem type."
          },
          "title": {
            "type": "string",
            "description": "A short, human summary (follows Accept-Language)."
          },
          "status": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "The HTTP status."
          },
          "code": {
            "type": "string",
            "enum": [
              "bad_request",
              "unknown_field",
              "invalid_cursor",
              "idempotency_key_required",
              "unauthorized",
              "key_revoked",
              "key_expired",
              "legacy_key",
              "test_keys_not_available",
              "key_owner_inactive",
              "insufficient_scope",
              "role_forbidden",
              "ip_not_allowed",
              "workspace_suspended",
              "feature_not_enabled",
              "key_suspended",
              "member_locked",
              "not_found",
              "method_not_allowed",
              "conflict",
              "outreach_paused",
              "already_decided",
              "idempotency_in_progress",
              "no_sender",
              "insufficient_credits",
              "too_large",
              "validation_failed",
              "send_blocked",
              "publish_blocked",
              "ad_publish_blocked",
              "ad_switch_blocked",
              "ad_network_unsupported",
              "post_schedule_blocked",
              "ads_by_plan",
              "idempotency_mismatch",
              "rate_limited",
              "send_cap_reached",
              "number_cap_reached",
              "server_error",
              "unavailable"
            ],
            "description": "Stable machine-readable code."
          },
          "detail": {
            "description": "What happened, for a person (follows Accept-Language).",
            "type": "string"
          },
          "instance": {
            "description": "The request id.",
            "type": "string"
          },
          "errors": {
            "description": "Field-level problems (validation_failed, unknown_field).",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "path",
                "code",
                "message"
              ],
              "additionalProperties": false
            }
          },
          "docs": {
            "type": "string",
            "description": "Where this code is explained."
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "code",
          "docs"
        ],
        "additionalProperties": {},
        "description": "RFC 9457 problem details."
      }
    }
  }
}