{
  "openapi": "3.1.0",
  "paths": {
    "/api/v1/contacts": {
      "post": {
        "description": "Upserts a contact in the organization the API key belongs to, keyed on email.\n\n`cancel_events` are processed first, then `events` are fired, so one request can replace\nthe journey a contact is on. Cancellations and other events are best effort.\n`assessment_abandoned` requires transactional acceptance: failures fail the request even if\nthe contact was already upserted. Only a matching `assessmentAbandonment` receipt with\n`status: accepted` confirms durable enrollment acceptance; delivery is not guaranteed.\nAn event whose name no active sequence subscribes to leaves its `key` unspent, so a later\nretry still enrolls.",
        "operationId": "contacts_upsert",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactUpsertDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactUpsertResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `contacts:write` scope; `required` names it. A member’s credential gets `insufficient_role`: members cannot call this operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Create or update a contact by email",
        "tags": [
          "Contacts",
          "Public API"
        ],
        "x-iris-changes": [
          "contacts",
          "sequences"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "contacts:write",
        "x-member-access": "deny"
      },
      "get": {
        "description": "Finds contacts in the key’s organization. Send at most one filter:\n\n- `q`: free text, matched against name, email and phone, without regard to case.\n- `email`: the exact email, without regard to case. Returns at most one contact.\n- `phone`: the exact phone number. Returns at most one contact.\n\nWith no filter, lists every contact, most recently seen first.\nA member’s credential finds only contacts linked to its locations. A MEMBER at the own-records level\nfinds only the clients of their own appointments.\n\nA MEMBER, and a MANAGER without the contacts power, get each contact’s `id`, `name`, `email` and\n`phone` only, listed by name. A MANAGER with the power gets whole contacts, as an owner does.",
        "operationId": "contacts_search",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "1-based page number",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size (capped at 100)",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Free text. Matches contacts whose name, email or phone contains it, without regard to case.",
            "schema": {
              "maxLength": 255,
              "type": "string"
            }
          },
          {
            "name": "email",
            "required": false,
            "in": "query",
            "description": "Exact email, without regard to case",
            "schema": {
              "format": "email",
              "type": "string"
            }
          },
          {
            "name": "phone",
            "required": false,
            "in": "query",
            "description": "Exact phone number with its country code. Spaces, dashes and brackets are ignored, so `+1 (415) 555-0100` works. Matches the contact's phone number, not a phone held in `custom_fields`.",
            "schema": {
              "example": "+14155550100",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactPageDto"
                }
              }
            }
          },
          "400": {
            "description": "More than one filter, or an invalid one"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `contacts:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Search contacts",
        "tags": [
          "Contacts",
          "Public API"
        ],
        "x-iris-scope": "contacts:read",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/contacts/{contactId}": {
      "get": {
        "description": "The contact with its pipeline stage, tags, custom fields and number of notes.\nA MEMBER, and a MANAGER without the contacts power, get its `id`, `name`, `email` and `phone` only.\nA MEMBER at the own-records level gets only the clients of their own appointments (404 otherwise).",
        "operationId": "contacts_get",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `contacts:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Get one contact",
        "tags": [
          "Contacts",
          "Public API"
        ],
        "x-iris-scope": "contacts:read",
        "x-member-access": "scoped"
      },
      "patch": {
        "description": "Changes only the fields sent. `stage_id` must be a stage of the organization’s pipeline,\nand every `custom_fields` key must be a custom field the organization defines: an unknown\none is a 400 that names it, and nothing is written. Returns the contact as `contacts_get` does.",
        "operationId": "contacts_update",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactUpdateDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, unknown custom field or unknown stage"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `contacts:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `contacts` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "Another contact already uses that phone number or email"
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Update a contact",
        "tags": [
          "Contacts",
          "Public API"
        ],
        "x-iris-changes": [
          "contacts"
        ],
        "x-iris-scope": "contacts:write",
        "x-manager-power": "contacts",
        "x-member-access": "deny"
      }
    },
    "/api/v1/contacts/{contactId}/notes": {
      "post": {
        "description": "The team sees the note on the contact. Notes cannot be edited or deleted.",
        "operationId": "contacts_add_note",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactNoteCreateDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactNoteDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `contacts:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `contacts` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: the key was sent before with other details, or before the caller’s access changed. `idempotency_in_progress`: the first call with the key is still running. `idempotency_outcome_unknown`: the first call failed after it started and may have taken effect, so read the current state before you retry with a new key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "`idempotency_unavailable`: an `idempotency_key` was sent, but the store that keeps it is down. The call did not run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Add a note to a contact",
        "tags": [
          "Contacts",
          "Public API"
        ],
        "x-iris-changes": [
          "contacts"
        ],
        "x-iris-idempotent": true,
        "x-iris-scope": "contacts:write",
        "x-manager-power": "contacts",
        "x-member-access": "deny"
      },
      "get": {
        "description": "The organization-shared notes on one contact, newest first: those `contacts_add_note` and Zapier write. `contacts_get` counts every note, so its `notes_count` can exceed `total` here.\nEach note gives its `body`, its `source` (`user`, `zapier` or `system`), its author when a team member wrote it, and when it was written.\nPage with `page` and `limit`. `limit` is at most 100 and defaults to 25: a larger `limit` answers 400.\nA `page` past the last note answers 400.\nA contact the credential cannot read answers 404, like one that does not exist.\nNotes that belong to one location are not listed: the ones a team member writes in the dashboard and the ones synced from GoHighLevel. They are private to their location and revisioned.\nA MEMBER, and a MANAGER without the contacts power, get `insufficient_role`: they read a contact’s identity only. A MANAGER with the contacts power reads the notes of contacts at their locations.",
        "operationId": "contacts_list_notes",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "1-based page number",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size (capped at 100)",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactNotePageDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid paging, or a `page` past the last note"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `contacts:read` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `contacts` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the notes of a contact",
        "tags": [
          "Contacts",
          "Public API"
        ],
        "x-iris-scope": "contacts:read",
        "x-manager-power": "contacts",
        "x-member-access": "deny"
      }
    },
    "/api/v1/contacts/{contactId}/tags": {
      "post": {
        "description": "Idempotent: adding a tag the contact already carries changes nothing. A tag the organization does not have yet is created.",
        "operationId": "contacts_add_tag",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactTagCreateDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactTagsDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `contacts:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `contacts` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "The organization has reached its tag limit"
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Add a tag to a contact",
        "tags": [
          "Contacts",
          "Public API"
        ],
        "x-iris-changes": [
          "contacts"
        ],
        "x-iris-scope": "contacts:write",
        "x-manager-power": "contacts",
        "x-member-access": "deny"
      }
    },
    "/api/v1/contacts/{contactId}/tags/{tag}": {
      "delete": {
        "description": "Idempotent: removing a tag the contact does not carry changes nothing and still answers 200.",
        "operationId": "contacts_remove_tag",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "tag",
            "required": true,
            "in": "path",
            "description": "Tag name, URL-encoded",
            "schema": {
              "type": "string",
              "maxLength": 120
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactTagsDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `contacts:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `contacts` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Remove a tag from a contact",
        "tags": [
          "Contacts",
          "Public API"
        ],
        "x-iris-changes": [
          "contacts"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "contacts:write",
        "x-manager-power": "contacts",
        "x-member-access": "deny"
      }
    },
    "/api/v1/contacts/{contactId}/suppress": {
      "post": {
        "description": "Honours an unsubscribe at once. `email` blocks every further email to the contact’s address\nand stops the contact’s email sequences.\n`sms` records an SMS opt-out, revokes consent and cancels the contact’s SMS sequences.\nThe contact is not told. An address that is already suppressed keeps its first record.",
        "operationId": "contacts_suppress",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactSuppressDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactSuppressResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or the contact has no address on a named channel"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `contacts:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `contacts` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Suppress a contact on email or SMS",
        "tags": [
          "Contacts",
          "Public API"
        ],
        "x-iris-changes": [
          "contacts",
          "sequences"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "contacts:write",
        "x-manager-power": "contacts",
        "x-member-access": "deny"
      }
    },
    "/api/v1/contacts/stages": {
      "get": {
        "description": "The stages of the organization’s pipeline, in the order the dashboard shows them.\nSend a stage’s `id` as `stage_id` to `contacts_update` to move a contact to it.\nAn organization with no pipeline stage field answers an empty list.\nThe answer’s `audience_field` is the audience rule `field` that tests a contact’s stage. Use it in an audience definition, with stage ids as values.",
        "operationId": "contacts_list_stages",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactStageListDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `contacts:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the organization’s pipeline stages",
        "tags": [
          "Contacts",
          "Public API"
        ],
        "x-iris-scope": "contacts:read",
        "x-member-access": "open"
      }
    },
    "/api/v1/contacts/{contactId}/interactions": {
      "get": {
        "description": "The calls, chats and SMS threads the assistant handled with one contact, most recent first. Email threads are not listed here: use `conversations_list`.\nFilter by `channel` or `status`. An interaction that booked an appointment names it in `appointment_id`.\nA `page` past the last interaction answers 400.\nThis does not list notes: `contacts_get` counts them.\nA MEMBER’s credential, and a location-limited key, see only the interactions at their locations, and\nonly for contacts they can read (404 otherwise). A MEMBER, and a MANAGER without the contacts power,\ndo not get `captured_fields`.",
        "operationId": "contacts_list_interactions",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "1-based page number",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size (capped at 100)",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "channel",
            "required": false,
            "in": "query",
            "description": "Only interactions on this channel",
            "schema": {
              "type": "string",
              "enum": [
                "voice",
                "chat",
                "sms"
              ]
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "Only interactions in this status",
            "schema": {
              "type": "string",
              "enum": [
                "in_progress",
                "completed",
                "abandoned"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactInteractionPageDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid paging, or a `page` past the last interaction"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `contacts:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the interactions of a contact",
        "tags": [
          "Contacts",
          "Public API"
        ],
        "x-iris-scope": "contacts:read",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/sequences": {
      "get": {
        "description": "Every sequence the API key’s organization owns, newest first. A manager or member sees organization-wide sequences and those of their locations.",
        "operationId": "sequences_list",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SequenceSummaryDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the organization’s sequences",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-scope": "sequences:read",
        "x-member-access": "open"
      },
      "post": {
        "description": "Creates an inactive draft from a name, a trigger and ordered steps. Nothing sends until\n`sequences_activate`. Sending `is_active: true` is a 400. Take triggers, variables and\nconditions from the discovery operations.",
        "operationId": "sequences_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SequenceCreateDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such audience in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: the key was sent before with other details, or before the caller’s access changed. `idempotency_in_progress`: the first call with the key is still running. `idempotency_outcome_unknown`: the first call failed after it started and may have taken effect, so read the current state before you retry with a new key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "`idempotency_unavailable`: an `idempotency_key` was sent, but the store that keeps it is down. The call did not run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Create a draft sequence",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [
          "sequences"
        ],
        "x-iris-idempotent": true,
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/enrollments": {
      "get": {
        "description": "Newest first. `email` resolves the contact in the key’s organization and then filters by\nit, so an email no contact carries returns an empty page rather than a 404.\n\nRead `next_step_due_at` for the next send time and fall back to `next_run_at`;\n`current_step_index` is the step, `created_at` is when the contact was enrolled, and\n`updated_at` read together with `status` is when a completed or cancelled enrollment ended.",
        "operationId": "sequences_list_enrollments",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "1-based page number",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size (capped at 100)",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "Only enrollments with this status",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "paused",
                "completed",
                "cancelled",
                "failed"
              ]
            }
          },
          {
            "name": "contact_id",
            "required": false,
            "in": "query",
            "description": "Only this contact's enrollments in the sequence",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "email",
            "required": false,
            "in": "query",
            "description": "Only the enrollments of the contact with this email, in the key’s organization. Matched without regard to case. Takes precedence over `contact_id`. An email no contact carries returns an empty page, not a 404. When more than one contact carries the email, the one that owns it as its identity is used.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceEnrollmentPageDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:read` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the contacts enrolled in one sequence",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-scope": "sequences:read",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      },
      "post": {
        "description": "Send `contact_id` or `email`. Safe to retry: a contact already active or paused in the\nsequence answers `status: skipped`, `reason: already_enrolled` with that enrollment, and\nnothing changes. An inactive sequence answers 409 `sequence_inactive`, a paused one 409\n`sequence_paused`. A sequence bound to a location enrolls only contacts linked to that\nlocation, and answers 409 `contact_not_at_location` for any other. A broadcast takes\ncontacts from its audience, not from this call.",
        "operationId": "sequences_enroll",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SequenceEnrollDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceEnrollResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Neither or both of contact_id and email, an unknown start step, or a broadcast"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`sequence_inactive`, `sequence_paused` or `contact_not_at_location`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Enroll a contact in a sequence",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [
          "sequences"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/contacts/{contactId}/enrollments": {
      "get": {
        "description": "Newest first. The contact must belong to the API key’s organization.",
        "operationId": "contacts_list_enrollments",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "1-based page number",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size (capped at 100)",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactEnrollmentPageDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:read` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List one contact’s enrollments across every sequence",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-scope": "sequences:read",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/me": {
      "get": {
        "description": "Returns the organization the credential belongs to, the key itself (or, for an OAuth access token, the connected client, its granted scopes and the person who granted it with their current role and locations), every scope a credential can carry, and the rate limit. A key with a role names it (MANAGER or MEMBER) and the manager powers it acts with, and a location-limited key lists its locations. Needs no scope: any live key or token may call it.",
        "operationId": "me_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Describe the calling API key or connected client, the role it acts at and the locations it reaches",
        "tags": [
          "Me",
          "Public API"
        ],
        "x-iris-scope": null,
        "x-member-access": "open"
      }
    },
    "/api/v1/appointments": {
      "get": {
        "description": "Appointments that overlap the window, earliest first. The window defaults to the next\n30 days and can span at most 92 days.\nCancelled appointments are left out. A repeating appointment appears once per occurrence.\nEvery occurrence has the series id as its `id`, `recurring: true` and its own `occurrence_start`.\nThe API cannot cancel or reschedule a repeating appointment: change it in the Iris dashboard.\n\n`contact_id` keeps the contact’s appointments only: bookings made for the contact, and\nbookings whose attendee phone or email is the contact’s.\n\nA member’s credential sees appointments at its own locations only. A MEMBER at the own-records level\nsees only the appointments where they are the team member.",
        "operationId": "appointments_list",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "1-based page number",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size (capped at 100)",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "contact_id",
            "required": false,
            "in": "query",
            "description": "Only this contact’s appointments: bookings made for the contact, and bookings whose attendee phone or email is the contact’s.",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "Start of the window. Defaults to now.",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "End of the window. Defaults to 30 days after `from`. At most 92 days after it.",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppointmentPageDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query, or a window that is empty or too long"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `appointments:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List appointments in a time window",
        "tags": [
          "Appointments",
          "Public API"
        ],
        "x-iris-scope": "appointments:read",
        "x-member-access": "scoped"
      },
      "post": {
        "description": "Two shapes. Send exactly one of `location_id` and `calendar_id`.\n\n- `location_id` (from `locations_list`), with `offering_id`, `team_member_id` and\n  `service_address` as the location needs. A staffed location books this way. Leave out\n  `team_member_id` to book the first team member who is free. Find times with\n  `appointments_availability` first.\n- `calendar_id` (from `calendars_list`) books a location that is not staffed on its Google calendar.\n\nWith either shape, the contact’s name, phone and email become the attendee, so reminders reach\nthem. The booking is made in the name of the user who created the API key.\nRetry with the same `idempotency_key` to get the first booking back rather than a second one.\nAt a staffed location a member’s credential books and checks only its own times, and changes only its own appointments. Anything else answers 403 `insufficient_role`. A manager’s credential with the appointments power books, checks and changes anyone’s appointments at its own locations.\n\nA refused `location_id` booking answers 409 with `error` set to one of these codes and a `message`:\n\n- `offering_required`: the location sells services. Choose one. The body carries `booking_options`.\n- `offering_not_offered_here`: the service is not offered here, or nobody here does it.\n- `team_member_not_eligible`: the team member does not work here, does not do this service, or does not cover the address.\n- `no_team_member_available`: nobody who can do it is free then.\n- `slot_taken`: the time is booked.\n- `outside_hours`: the time is outside booking hours, or outside the team member’s schedule.\n- `duration_mismatch`: the end time does not match the service’s `duration_minutes`.\n- `address_out_of_area`: no territory of this location covers the postal code.\n- `location_changed`: the location changed while booking. Check availability again.\n\nA `calendar_id` slot that is not available is a 409 with no code.\nThe same `idempotency_key` with other details is a 409 too, with no code.",
        "operationId": "appointments_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppointmentCreateDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppointmentDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, both or neither of `location_id` and `calendar_id`, staffed fields with `calendar_id`, or an end time that is not after the start"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `appointments:write` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such location, calendar or contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "A refused `location_id` booking answers 409 with `error` set to one of these codes and a `message`:\n\n- `offering_required`: the location sells services. Choose one. The body carries `booking_options`.\n- `offering_not_offered_here`: the service is not offered here, or nobody here does it.\n- `team_member_not_eligible`: the team member does not work here, does not do this service, or does not cover the address.\n- `no_team_member_available`: nobody who can do it is free then.\n- `slot_taken`: the time is booked.\n- `outside_hours`: the time is outside booking hours, or outside the team member’s schedule.\n- `duration_mismatch`: the end time does not match the service’s `duration_minutes`.\n- `address_out_of_area`: no territory of this location covers the postal code.\n- `location_changed`: the location changed while booking. Check availability again.\n\nA `calendar_id` slot that is not available is a 409 with no code.\nThe same `idempotency_key` with other details is a 409 too, with no code."
          },
          "422": {
            "description": "The calendar is not active, or the key has no creator to book in the name of, or that user is no longer an active member of the organization"
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Book an appointment for a contact",
        "tags": [
          "Appointments",
          "Public API"
        ],
        "x-iris-changes": [
          "appointments"
        ],
        "x-iris-idempotent": true,
        "x-iris-scope": "appointments:write",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/appointments/availability": {
      "get": {
        "description": "The open slots the booking check would accept, the same ones the Iris voice agent offers.\nSend `offering_id` for a staffed location that sells services: the slots are that service’s\nlength, and each names the team members free for it. Send `team_member_id` for one person.\nSend `postal_code` for a home visit: only team members who cover it.\nA member’s credential checks its own locations only.\nAt a staffed location a member’s credential books and checks only its own times, and changes only its own appointments. Anything else answers 403 `insufficient_role`. A manager’s credential with the appointments power books, checks and changes anyone’s appointments at its own locations.\nBook a slot with `appointments_create`, its `start` as `start_time` and its `end` as `end_time`.\n\nA request that cannot be served answers 409 with `error` set to one of these codes and a `message`:\n\n- `offering_not_offered_here` or `unknown_offering`: the service is not bookable here.\n- `team_member_not_eligible` or `unknown_team_member`: the team member cannot take this request here.\n- `offering_required`: the location sells services. Send `offering_id`.\n- `address_out_of_area`: no territory of this location covers the postal code.",
        "operationId": "appointments_availability",
        "parameters": [
          {
            "name": "location_id",
            "required": true,
            "in": "query",
            "description": "A location from `locations_list`",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "date",
            "required": true,
            "in": "query",
            "description": "The day, in the location’s time zone",
            "schema": {
              "example": "2026-09-24",
              "type": "string"
            }
          },
          {
            "name": "offering_id",
            "required": false,
            "in": "query",
            "description": "Only slots for this service, at its length",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "team_member_id",
            "required": false,
            "in": "query",
            "description": "Only slots this team member is free for",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "postal_code",
            "required": false,
            "in": "query",
            "description": "The customer’s postal code for a home visit. Only people who cover it.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "country_code",
            "required": false,
            "in": "query",
            "description": "ISO 3166-1 alpha-2 country of `postal_code`",
            "schema": {
              "example": "US",
              "type": "string"
            }
          },
          {
            "name": "duration_minutes",
            "required": false,
            "in": "query",
            "description": "Ignored when `offering_id` is sent",
            "schema": {
              "minimum": 1,
              "maximum": 1440,
              "default": 30,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvailabilityDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `appointments:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such location in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "A request that cannot be served answers 409 with `error` set to one of these codes and a `message`:\n\n- `offering_not_offered_here` or `unknown_offering`: the service is not bookable here.\n- `team_member_not_eligible` or `unknown_team_member`: the team member cannot take this request here.\n- `offering_required`: the location sells services. Send `offering_id`.\n- `address_out_of_area`: no territory of this location covers the postal code."
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Find open slots at a location on one day",
        "tags": [
          "Appointments",
          "Public API"
        ],
        "x-iris-scope": "appointments:read",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/appointments/{appointmentId}": {
      "get": {
        "description": "The appointment in any status, cancelled included.\nFor a repeating appointment, `recurring` is true and `series_id` names the series.",
        "operationId": "appointments_get",
        "parameters": [
          {
            "name": "appointmentId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppointmentDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `appointments:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such appointment in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Get one appointment",
        "tags": [
          "Appointments",
          "Public API"
        ],
        "x-iris-scope": "appointments:read",
        "x-member-access": "scoped"
      },
      "patch": {
        "description": "Changes only the fields sent: `title`, `description` (the appointment’s notes) and the attendee’s\n`attendee_name`, `attendee_phone`, `attendee_email` and `attendee_notes`. A nullable field set to\n`null` is cleared. Send at least one field. Mirrors the change to Google Calendar, which keeps an\nold description or attendee email that was cleared (the dashboard edit does the same).\nThe time, status, team member, service, location and address do not change here. A body that names\none answers 400 with the operation to use: `appointments_reschedule` moves the appointment and\n`appointments_cancel` cancels it.\nA repeating appointment answers 409 `recurring_series_not_supported` and nothing changes.\nAt a staffed location a member’s credential books and checks only its own times, and changes only its own appointments. Anything else answers 403 `insufficient_role`. A manager’s credential with the appointments power books, checks and changes anyone’s appointments at its own locations.",
        "operationId": "appointments_update",
        "parameters": [
          {
            "name": "appointmentId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppointmentUpdateDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppointmentDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, no field to change, or a time, status, staff or resource field"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `appointments:write` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such appointment in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`recurring_series_not_supported`: the appointment repeats. Change it in the Iris dashboard."
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Change an appointment’s title, notes or attendee details",
        "tags": [
          "Appointments",
          "Public API"
        ],
        "x-iris-changes": [
          "appointments"
        ],
        "x-iris-scope": "appointments:write",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/appointments/{appointmentId}/reschedule": {
      "post": {
        "description": "Sets the new start and end, moves the Google Calendar copy, and re-times the appointment reminders.\nA repeating appointment answers 409 `recurring_series_not_supported` and nothing changes:\none occurrence carries the series id, so a change would move every occurrence. Change it in the Iris dashboard.\nAt a staffed location a member’s credential books and checks only its own times, and changes only its own appointments. Anything else answers 403 `insufficient_role`. A manager’s credential with the appointments power books, checks and changes anyone’s appointments at its own locations.\nA cancelled appointment answers 409 `appointment_cancelled` and nothing changes: book a new one.",
        "operationId": "appointments_reschedule",
        "parameters": [
          {
            "name": "appointmentId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppointmentRescheduleDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppointmentDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or an end time that is not after the start"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `appointments:write` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such appointment in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`recurring_series_not_supported`: the appointment repeats. Change it in the Iris dashboard.\n\n`appointment_cancelled`: the appointment is cancelled. Book a new one."
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Move an appointment to a new time",
        "tags": [
          "Appointments",
          "Public API"
        ],
        "x-iris-changes": [
          "appointments"
        ],
        "x-iris-scope": "appointments:write",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/appointments/{appointmentId}/cancel": {
      "post": {
        "description": "Cancels the appointment, removes it from Google Calendar and stops its reminders.\nIdempotent: cancelling a cancelled appointment returns it and only retries the Google removal.\nA repeating appointment answers 409 `recurring_series_not_supported` and nothing changes:\none occurrence carries the series id, so a cancel would cancel every occurrence. Change it in the Iris dashboard.\nAt a staffed location a member’s credential books and checks only its own times, and changes only its own appointments. Anything else answers 403 `insufficient_role`. A manager’s credential with the appointments power books, checks and changes anyone’s appointments at its own locations.",
        "operationId": "appointments_cancel",
        "parameters": [
          {
            "name": "appointmentId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppointmentDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `appointments:write` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such appointment in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`recurring_series_not_supported`: the appointment repeats. Change it in the Iris dashboard."
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cancel an appointment",
        "tags": [
          "Appointments",
          "Public API"
        ],
        "x-iris-changes": [
          "appointments"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "appointments:write",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/calendars": {
      "get": {
        "description": "One calendar per location with an active Google calendar connection. Pass its `id` as `calendar_id` to `appointments_create`. A member’s credential lists its own locations’ calendars only.",
        "operationId": "calendars_list",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CalendarDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `appointments:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the calendars appointments can be booked on",
        "tags": [
          "Calendars",
          "Public API"
        ],
        "x-iris-scope": "appointments:read",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/locations": {
      "get": {
        "description": "Every active location with its time zone. A member’s credential lists its own locations only.\n`staffed: true` means the location books by team member: call `locations_booking_options`,\nthen book with `location_id`. A location that is not staffed can also be booked on its calendar\nfrom `calendars_list`.",
        "operationId": "locations_list",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/LocationDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `appointments:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the locations appointments can be booked at",
        "tags": [
          "Locations",
          "Public API"
        ],
        "x-iris-scope": "appointments:read",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/locations/{locationId}/booking-options": {
      "get": {
        "description": "The active services offered at the location, with their length and buffers and the team\nmembers who do each one, and every team member bookable there, in booking priority order.\nSend a service `id` as `offering_id` and a team member `id` as `team_member_id` to\n`appointments_availability` and `appointments_create`.\nA location that is not staffed and sells no services answers with empty lists.\nA member’s credential sees only itself and its own services, and every buffer as 0.\nA manager’s credential with the appointments power sees everything, as an owner’s does.",
        "operationId": "locations_booking_options",
        "parameters": [
          {
            "name": "locationId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookingOptionsDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `appointments:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such location in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the services and team members a location books",
        "tags": [
          "Locations",
          "Public API"
        ],
        "x-iris-scope": "appointments:read",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/territories": {
      "get": {
        "description": "The areas the business travels to, each served from one location, with its postal codes and\nthe team members who cover it. A customer whose postal code is in no active territory cannot\nbook a home visit: `appointments_create` answers 409 `address_out_of_area`.\nAn organization that does not book by territory answers an empty list. Inactive territories\nare listed too, and book nothing.",
        "operationId": "territories_list",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TerritoryDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `appointments:read` scope; `required` names it. A member’s credential gets `insufficient_role`: members cannot call this operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the service territories and their postal codes",
        "tags": [
          "Territories",
          "Public API"
        ],
        "x-iris-scope": "appointments:read",
        "x-member-access": "deny"
      }
    },
    "/api/v1/conversations": {
      "get": {
        "description": "Newest activity first. Pages by cursor: pass `next_cursor` back as `cursor` until it is null.\nA page can hold fewer than `limit` items and still have a next page.\nEvery channel when `channel` is left out. A search (`q`) matches email and SMS only, so it leaves chat out.\nA MEMBER at the own-records level gets only the conversations of the clients of their own appointments.",
        "operationId": "conversations_list",
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "The `next_cursor` of the page before. Leave out for the first page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "channel",
            "required": false,
            "in": "query",
            "description": "Only this channel. Every channel when left out. A search (`q`) leaves chat out.",
            "schema": {
              "type": "string",
              "enum": [
                "email",
                "sms",
                "chat"
              ]
            }
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Free text search",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationPageDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `conversations:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List email, SMS and web chat conversations",
        "tags": [
          "Conversations",
          "Public API"
        ],
        "x-iris-scope": "conversations:read",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/conversations/{conversationId}": {
      "get": {
        "description": "Every message of an email or chat conversation, or the latest 50 messages of an SMS conversation, oldest first.\nA chat conversation shows the visitor’s messages (inbound) and the AI’s and staff replies (outbound), not tool calls or system notes.\n`response_mode` says whether the AI or a person answers an SMS or chat conversation.\nReading an email conversation marks it as read: its unread count in the Iris inbox goes to zero.",
        "operationId": "conversations_get",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDetailDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `conversations:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such conversation in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Get one conversation with its messages",
        "tags": [
          "Conversations",
          "Public API"
        ],
        "x-iris-scope": "conversations:read",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/conversations/{conversationId}/reply": {
      "post": {
        "description": "Sends `body` into the conversation on its own channel, as the dashboard inbox does, and returns the messages it stored.\nSMS: a text to the conversation’s number from its line, at most 1600 characters. The number must have consented and must not have opted out.\nChat: an operator message to the visitor, at most 4000 characters. Email: an email to the contact, threaded.\nAn SMS or chat reply hands the conversation to a person for 30 minutes: the AI stops answering until then, unless it is on hold.\nA staff member (MEMBER) key needs their SMS setting on for every channel, email and chat too. On every channel it\nreaches only their own clients’ conversations at their locations. A manager needs the contacts power.\nA staff member’s email reply also follows the dashboard rule, which can refuse it with 403.\nAny conversation the caller does not reach answers 404. Without `idempotency_key`, a retry after a 5xx can send twice.\nIn chat, on a member key, two identical replies sent at the same moment may report the same message id. The text is stored once per request.",
        "operationId": "conversations_reply",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConversationReplyDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationReplyResultDto"
                }
              }
            }
          },
          "400": {
            "description": "A blank or missing body, or a body too long for the channel"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The caller may not reply on this channel (for example a manager without the contacts power)\n\nThe key does not carry the `conversations:write` scope; `required` names it. A member’s credential gets `insufficient_role` unless the member’s SMS setting is on, and a manager’s unless they hold the `contacts` power",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such conversation in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`sms_not_permitted`: the SMS recipient opted out or has not consented\n\n`idempotency_key_reused`: the key was sent before with other details, or before the caller’s access changed. `idempotency_in_progress`: the first call with the key is still running. `idempotency_outcome_unknown`: the first call failed after it started and may have taken effect, so read the current state before you retry with a new key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "`phone_line_invalid`: the SMS line is gone. `no_acting_user`: an email reply from a key with no person to send as"
          },
          "429": {
            "description": "The daily SMS cap for this contact is reached\n\nMore than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "502": {
            "description": "The SMS or email provider refused the send"
          },
          "503": {
            "description": "`idempotency_unavailable`: an `idempotency_key` was sent, but the store that keeps it is down. The call did not run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Reply in an email, SMS or web chat conversation",
        "tags": [
          "Conversations",
          "Public API"
        ],
        "x-iris-changes": [
          "conversations"
        ],
        "x-iris-confirm": true,
        "x-iris-idempotent": true,
        "x-iris-scope": "conversations:write",
        "x-member-access": "sms_setting"
      }
    },
    "/api/v1/conversations/{conversationId}/hold": {
      "post": {
        "description": "Sets `response_mode` to `human_manual`: the AI does not answer the contact until someone resumes it. Safe to repeat.\nAn email conversation has no AI to hold: the answer is 422 `channel_not_supported`.\nA staff member (MEMBER) key needs their SMS setting on for every channel, chat too. On every channel it reaches only\ntheir own clients’ conversations at their locations. A manager needs the contacts power.\nA staff member’s SMS hold also follows the dashboard rule, which can refuse it with 403. Any conversation the caller does not reach answers 404.",
        "operationId": "conversations_hold",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationResponseModeResultDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `conversations:write` scope; `required` names it. A member’s credential gets `insufficient_role` unless the member’s SMS setting is on, and a manager’s unless they hold the `contacts` power",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such conversation in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "`channel_not_supported`: an email conversation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Hold an SMS or web chat conversation for a person: the AI stops answering",
        "tags": [
          "Conversations",
          "Public API"
        ],
        "x-iris-changes": [
          "conversations"
        ],
        "x-iris-scope": "conversations:write",
        "x-member-access": "sms_setting"
      }
    },
    "/api/v1/conversations/{conversationId}/resume": {
      "post": {
        "description": "Sets `response_mode` to `ai_auto`: the AI answers the contact again. An SMS contact gets a short note that the AI is back each time the call runs.\nA retry with the same `idempotency_key` answers the first result and does not send the note again.\nAn email conversation has no AI to resume: the answer is 422 `channel_not_supported`.\nA staff member (MEMBER) key needs their SMS setting on for every channel, chat too. On every channel it reaches only\ntheir own clients’ conversations at their locations. A manager needs the contacts power.\nA staff member’s SMS resume also follows the dashboard rule, which can refuse it with 403. Any conversation the caller does not reach answers 404.",
        "operationId": "conversations_resume",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdempotencyKeyDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationResponseModeResultDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `conversations:write` scope; `required` names it. A member’s credential gets `insufficient_role` unless the member’s SMS setting is on, and a manager’s unless they hold the `contacts` power",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such conversation in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: the key was sent before with other details, or before the caller’s access changed. `idempotency_in_progress`: the first call with the key is still running. `idempotency_outcome_unknown`: the first call failed after it started and may have taken effect, so read the current state before you retry with a new key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "`channel_not_supported`: an email conversation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "`idempotency_unavailable`: an `idempotency_key` was sent, but the store that keeps it is down. The call did not run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Hand an SMS or web chat conversation back to the AI",
        "tags": [
          "Conversations",
          "Public API"
        ],
        "x-iris-changes": [
          "conversations"
        ],
        "x-iris-confirm": true,
        "x-iris-idempotent": true,
        "x-iris-scope": "conversations:write",
        "x-member-access": "sms_setting"
      }
    },
    "/api/v1/conversations/sms": {
      "post": {
        "description": "Sends to `contact_id`’s phone or to `phone`. Send exactly one of them. The text goes from the\nnumber of the contact’s location when that number can text, else from the organization’s\ndefault SMS number, and joins the contact’s thread on that number, filed under that location.\nFor a manager, only their own locations count. A staff member (MEMBER) may send only while\ntheir SMS setting is on, and only to their own clients at their locations: any other contact\nor number answers 404. The recipient must have active SMS consent and must not have opted out:\notherwise the answer is 409 `sms_not_permitted` and nothing is sent. The daily per-contact cap\napplies. Without `idempotency_key`, a retry after a 5xx can send twice.",
        "operationId": "conversations_send_sms",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SmsSendDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SentSmsDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, both or neither recipient, or a contact with no phone"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `conversations:write` scope; `required` names it. A member’s credential gets `insufficient_role` unless the member’s SMS setting is on, and a manager’s unless they hold the `contacts` power",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization, or (for a manager or staff member) none they reach: a manager’s are at their locations, a staff member’s are their own clients there. A staff member also gets 404 when the contact’s thread on that number belongs to another location",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`sms_not_permitted`: the recipient opted out or has not consented\n\n`idempotency_key_reused`: the key was sent before with other details, or before the caller’s access changed. `idempotency_in_progress`: the first call with the key is still running. `idempotency_outcome_unknown`: the first call failed after it started and may have taken effect, so read the current state before you retry with a new key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "422": {
            "description": "No number can text the contact (no location number and no default), the daily cap is reached, the provider refused the send, or (for a manager) the contact’s thread on that number belongs to another location"
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "`idempotency_unavailable`: an `idempotency_key` was sent, but the store that keeps it is down. The call did not run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Send an SMS to a contact who has consented",
        "tags": [
          "Conversations",
          "Public API"
        ],
        "x-iris-changes": [
          "conversations"
        ],
        "x-iris-confirm": true,
        "x-iris-idempotent": true,
        "x-iris-scope": "conversations:write",
        "x-member-access": "sms_setting"
      }
    },
    "/api/v1/contacts/{contactId}/sms-consent": {
      "post": {
        "description": "`opt_in` records consent the contact gave you, for example on your web form. Iris may text\nthe contact a one-time confirmation. A contact who texted STOP cannot be opted back in\nthis way: the answer is 409 `sms_not_permitted`, and the contact must text START.\n`opt_out` revokes consent, suppresses the number and cancels the contact’s SMS sequences.\nThe contact is not told. Both are safe to repeat.",
        "operationId": "contacts_record_sms_consent",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SmsConsentDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SmsConsentResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or the contact has no phone number"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `contacts:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `contacts` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`sms_not_permitted`: the contact opted out by text\n\n`idempotency_key_reused`: the key was sent before with other details, or before the caller’s access changed. `idempotency_in_progress`: the first call with the key is still running. `idempotency_outcome_unknown`: the first call failed after it started and may have taken effect, so read the current state before you retry with a new key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "`idempotency_unavailable`: an `idempotency_key` was sent, but the store that keeps it is down. The call did not run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Record a contact’s SMS opt-in or opt-out",
        "tags": [
          "Conversations",
          "Public API"
        ],
        "x-iris-changes": [
          "contacts",
          "sequences"
        ],
        "x-iris-confirm": true,
        "x-iris-idempotent": true,
        "x-iris-scope": "contacts:write",
        "x-manager-power": "contacts",
        "x-member-access": "deny"
      }
    },
    "/api/v1/calls": {
      "get": {
        "description": "Newest first. Pages by cursor: pass `next_cursor` back as `cursor` until it is null.\n`contact_id` keeps the calls to or from the contact’s phone number. A contact with no phone\nnumber has no calls. A MEMBER (staff) gets only the calls of the clients of their own appointments,\nat either access level. A MEMBER with no linked staff profile gets an empty list.",
        "operationId": "calls_list",
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "The `next_cursor` of the page before. Leave out for the first page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "contact_id",
            "required": false,
            "in": "query",
            "description": "Only calls to or from this contact’s phone number",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "Only calls that started at or after this time",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Only calls that started at or before this time",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallPageDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query, or a cursor from another query"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `calls:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List calls",
        "tags": [
          "Calls",
          "Public API"
        ],
        "x-iris-scope": "calls:read",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/calls/{callId}": {
      "get": {
        "description": "The call, its full transcript in order, and whether a recording exists.\nA MEMBER (staff) reads only the calls of their own clients. Any other call answers 404.",
        "operationId": "calls_get",
        "parameters": [
          {
            "name": "callId",
            "required": true,
            "in": "path",
            "description": "The `id` from `calls_list`",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `calls:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such call in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "502": {
            "description": "The voice provider did not return the call. Retry once."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Get one call with its transcript",
        "tags": [
          "Calls",
          "Public API"
        ],
        "x-iris-scope": "calls:read",
        "x-member-access": "scoped"
      }
    },
    "/api/v1/audiences": {
      "get": {
        "description": "Every audience that is not archived, newest first. Only a `static` audience takes members.",
        "operationId": "audiences_list",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AudienceSummaryDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `audiences:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the organization’s audiences",
        "tags": [
          "Audiences",
          "Public API"
        ],
        "x-iris-scope": "audiences:read",
        "x-member-access": "open"
      },
      "post": {
        "description": "A `dynamic` audience (the default) holds every contact that matches `definition`. A `static`\naudience holds the contacts added with `audiences_add_member`, and needs no definition.\n`kind` cannot change later. Check a definition with `audiences_preview_count` first: it\nrejects unknown fields and ops that a create stores without resolving.\nLimits: name 200 characters, description 2000, at most 50 rules in one flat list, field 200\ncharacters, a string value 1000 characters, a list value 500 items. Over a limit answers 400.\n\nExample: contacts with at least 2 calls and an email, on the `plan` custom field gold or platinum:\n`{\"name\": \"Engaged gold\", \"definition\": {\"match\": \"all\", \"rules\": [{\"field\": \"total_calls\", \"op\": \"gte\",\n\"value\": 2}, {\"field\": \"email\", \"op\": \"exists\"}, {\"field\": \"field_values.plan\", \"op\": \"in\", \"value\":\n[\"gold\", \"platinum\"]}]}}`",
        "operationId": "audiences_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AudienceCreateDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body or definition"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `audiences:write` scope; `required` names it. A member’s credential gets `insufficient_role`: members cannot call this operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: the key was sent before with other details, or before the caller’s access changed. `idempotency_in_progress`: the first call with the key is still running. `idempotency_outcome_unknown`: the first call failed after it started and may have taken effect, so read the current state before you retry with a new key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "`idempotency_unavailable`: an `idempotency_key` was sent, but the store that keeps it is down. The call did not run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Create an audience",
        "tags": [
          "Audiences",
          "Public API"
        ],
        "x-iris-changes": [
          "audiences"
        ],
        "x-iris-idempotent": true,
        "x-iris-scope": "audiences:write",
        "x-member-access": "deny"
      }
    },
    "/api/v1/audiences/{audienceId}": {
      "get": {
        "description": "Reads an archived audience too. `definition` holds the rules of a dynamic audience.",
        "operationId": "audiences_get",
        "parameters": [
          {
            "name": "audienceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `audiences:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such audience in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Read one audience with its definition",
        "tags": [
          "Audiences",
          "Public API"
        ],
        "x-iris-scope": "audiences:read",
        "x-member-access": "open"
      },
      "patch": {
        "description": "Changes only the fields sent. `definition` replaces the whole definition: read it with\n`audiences_get`, edit it, and send it back. A channel filter stored inside the old definition is\nkept. `kind` cannot change, and is ignored here.\nLimits: name 200 characters, description 2000, at most 50 rules in one flat list, field 200\ncharacters, a string value 1000 characters, a list value 500 items. Over a limit answers 400.\n`is_archived: false` restores an archived audience. To archive one, use `audiences_archive`.",
        "operationId": "audiences_update",
        "parameters": [
          {
            "name": "audienceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AudienceUpdateDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body or definition. Nothing changes."
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `audiences:write` scope; `required` names it. A member’s credential gets `insufficient_role`: members cannot call this operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such audience in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Change an audience",
        "tags": [
          "Audiences",
          "Public API"
        ],
        "x-iris-changes": [
          "audiences"
        ],
        "x-iris-scope": "audiences:write",
        "x-member-access": "deny"
      }
    },
    "/api/v1/audiences/{audienceId}/archive": {
      "post": {
        "description": "Idempotent. An archived audience leaves `audiences_list`, and `audiences_get` still reads it.\nRestore it with `audiences_update` and `is_archived: false`.",
        "operationId": "audiences_archive",
        "parameters": [
          {
            "name": "audienceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `audiences:write` scope; `required` names it. A member’s credential gets `insufficient_role`: members cannot call this operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such audience in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Archive an audience",
        "tags": [
          "Audiences",
          "Public API"
        ],
        "x-iris-changes": [
          "audiences"
        ],
        "x-iris-scope": "audiences:write",
        "x-member-access": "deny"
      }
    },
    "/api/v1/audiences/{audienceId}/count": {
      "get": {
        "description": "A static audience counts its members. A dynamic audience counts the contacts its definition\nmatches now. Opted-out and suppressed contacts are still counted: they are removed when a\nmessage is sent. To count a draft definition, use `audiences_preview_count`.",
        "operationId": "audiences_count",
        "parameters": [
          {
            "name": "audienceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceCountDto"
                }
              }
            }
          },
          "400": {
            "description": "The stored definition names a field or op that is not allowed"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `audiences:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such audience in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Count the contacts in a saved audience",
        "tags": [
          "Audiences",
          "Public API"
        ],
        "x-iris-scope": "audiences:read",
        "x-member-access": "open"
      }
    },
    "/api/v1/audiences/preview-count": {
      "post": {
        "description": "Send a definition as the body. Nothing is saved. It checks every field and op, so a 400 here\nnames what to fix before `audiences_create` or `audiences_update`. Opted-out and suppressed\ncontacts are still counted. Limits: at most 50 rules in one flat list, field 200 characters, a\nstring value 1000 characters, a list value 500 items. Over a limit answers 400. Other keys are\ndropped.",
        "operationId": "audiences_preview_count",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AudienceFilterDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceCountDto"
                }
              }
            }
          },
          "400": {
            "description": "A field, op or value that is not allowed"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `audiences:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Count the contacts a draft definition matches",
        "tags": [
          "Audiences",
          "Public API"
        ],
        "x-iris-changes": [],
        "x-iris-scope": "audiences:read",
        "x-member-access": "open"
      }
    },
    "/api/v1/audiences/{audienceId}/contacts": {
      "get": {
        "description": "A static audience lists its members. A dynamic audience lists the contacts its definition\nmatches now, opted-out contacts included. Pass `next_cursor` back as `cursor` for the next page.\n`limit` is 1 to 100 (default 25), and `cursor` at most 1000 characters. Out of range answers 400.",
        "operationId": "audiences_list_members",
        "parameters": [
          {
            "name": "audienceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "The `next_cursor` of the page before. Leave out for the first page.",
            "schema": {
              "maxLength": 1000,
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceContactPageDto"
                }
              }
            }
          },
          "400": {
            "description": "A malformed cursor or limit"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `audiences:read` scope; `required` names it. A member’s credential gets `insufficient_role`: members cannot call this operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such audience in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the contacts in an audience",
        "tags": [
          "Audiences",
          "Public API"
        ],
        "x-iris-scope": "audiences:read",
        "x-member-access": "deny"
      }
    },
    "/api/v1/audiences/{audienceId}/members": {
      "post": {
        "description": "Idempotent: adding a member changes nothing. A new member can start the sequences that watch the audience.",
        "operationId": "audiences_add_member",
        "parameters": [
          {
            "name": "audienceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AudienceMemberAddDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceMembershipDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or a dynamic audience"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `audiences:write` scope; `required` names it. A member’s credential gets `insufficient_role`: members cannot call this operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such audience or contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Add a contact to a static audience",
        "tags": [
          "Audiences",
          "Public API"
        ],
        "x-iris-changes": [
          "audiences"
        ],
        "x-iris-scope": "audiences:write",
        "x-member-access": "deny"
      }
    },
    "/api/v1/audiences/{audienceId}/members/{contactId}": {
      "delete": {
        "description": "Idempotent: removing a contact who is not a member changes nothing and still answers 200.",
        "operationId": "audiences_remove_member",
        "parameters": [
          {
            "name": "audienceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceMembershipDto"
                }
              }
            }
          },
          "400": {
            "description": "A dynamic audience"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `audiences:write` scope; `required` names it. A member’s credential gets `insufficient_role`: members cannot call this operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such audience or contact in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Remove a contact from a static audience",
        "tags": [
          "Audiences",
          "Public API"
        ],
        "x-iris-changes": [
          "audiences"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "audiences:write",
        "x-member-access": "deny"
      }
    },
    "/api/v1/forms": {
      "get": {
        "description": "Every form of the organization, newest first, whatever its status. A form’s `id` names it in `forms_get` and `forms_list_submissions`.",
        "operationId": "forms_list",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FormDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `forms:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the organization’s forms",
        "tags": [
          "Forms",
          "Public API"
        ],
        "x-iris-scope": "forms:read",
        "x-member-access": "open"
      }
    },
    "/api/v1/forms/{formId}": {
      "get": {
        "description": "The form and its fields in display order. Each field’s `key` is the key of its answer in a submission `payload`. The form’s submission key is never returned.",
        "operationId": "forms_get",
        "parameters": [
          {
            "name": "formId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormDetailDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `forms:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such form in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Get one form with its fields",
        "tags": [
          "Forms",
          "Public API"
        ],
        "x-iris-scope": "forms:read",
        "x-member-access": "open"
      }
    },
    "/api/v1/forms/{formId}/submissions": {
      "get": {
        "description": "Newest first, with the contact each one created or updated and the answers as posted.\nPages by `page` and `limit`: read on until `page * limit` reaches `total`.\n`status`, `from`, `to` and `search` narrow the list. Submissions hold personal data.\nA MEMBER’s credential cannot call this operation, as a member cannot open the inbox.",
        "operationId": "forms_list_submissions",
        "parameters": [
          {
            "name": "formId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "1-based page number. (page - 1) * limit must be at most 2147483647.",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size (capped at 100)",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "accepted",
                "spam"
              ]
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "ISO 8601 datetime with a time part. Only submissions at or after it.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "ISO 8601 datetime with a time part. Only submissions at or before it. At most 366 days after `from`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "Case-insensitive match on part of the contact's email or the submitted email. At most 320 characters.",
            "schema": {
              "maxLength": 320,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormSubmissionPageDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `forms:read` scope; `required` names it. A member’s credential gets `insufficient_role`: members cannot call this operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such form in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the submissions of a form",
        "tags": [
          "Forms",
          "Public API"
        ],
        "x-iris-scope": "forms:read",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/capabilities": {
      "get": {
        "description": "Read before you build a sequence. `multi_trigger_writes_enabled` says whether a sequence may carry more than one trigger.",
        "operationId": "sequences_capabilities",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceCapabilitiesDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "What sequence authoring this server allows",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-scope": "sequences:read",
        "x-member-access": "open"
      }
    },
    "/api/v1/sequences/triggers": {
      "get": {
        "description": "Use a `key` whose `authorable` is true as `trigger_type`. The `event` trigger lists the event names this organization has seen.",
        "operationId": "sequences_list_triggers",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SequenceTriggerDescriptorDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the triggers a sequence can start on",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-scope": "sequences:read",
        "x-member-access": "open"
      }
    },
    "/api/v1/sequences/send-schedules": {
      "get": {
        "description": "A send window sets the days and hours a sequence may send. Use an `id` as `send_schedule_id` on\n`sequences_create` or `sequences_update`. The window with `is_default` true applies to a sequence\nthat names none. This is not the broadcast schedule of `sequences_set_schedule`, which sets when a\nbroadcast starts. Paged by `page` (at most 1000) and `limit` (at most 100).",
        "operationId": "sequences_list_send_schedules",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "1-based page number, at most 1000",
            "schema": {
              "minimum": 1,
              "maximum": 1000,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size (capped at 100)",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendSchedulePageDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid paging, or a `page` past the last window"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the send windows a sequence can use",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-scope": "sequences:read",
        "x-member-access": "open"
      }
    },
    "/api/v1/sequences/variables": {
      "get": {
        "description": "Write a token as `{{token}}` in a subject, preheader or body. The list includes the organization’s CRM fields.",
        "operationId": "sequences_list_variables",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceVariableCatalogDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the variables step copy may use",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-scope": "sequences:read",
        "x-member-access": "open"
      }
    },
    "/api/v1/sequences/condition-vocabulary": {
      "get": {
        "description": "A condition is an object such as `{ \"signal\": \"replied\", \"occurred\": true, \"windowMinutes\": 1440 }`. Use a signal with `exit_available` in an exit condition, and one with `routing_status: available` on a branch edge.",
        "operationId": "sequences_get_condition_vocabulary",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SequenceConditionSignalDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "List the signals a condition can test",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-scope": "sequences:read",
        "x-member-access": "open"
      }
    },
    "/api/v1/sequences/{sequenceId}": {
      "get": {
        "description": "The sequence with its status, triggers, steps, branch edges, exit conditions and send window. Read it before you change it.",
        "operationId": "sequences_get",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:read` scope; `required` names it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Get one sequence with its steps",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-scope": "sequences:read",
        "x-member-access": "open"
      },
      "patch": {
        "description": "Changes only the fields sent. `steps`, `edges` and `exit_conditions` each replace the whole\nlist: read the sequence with `sequences_get`, edit it, and send the full list back. Keep each\n`step_key`. `is_active: false` turns the sequence off and cancels every enrollment. To hold\ncontacts in place, use `sequences_pause` instead.",
        "operationId": "sequences_update",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SequenceUpdateDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such sequence in this organization\n\nNo such audience in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Change a sequence",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [
          "sequences"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/activate": {
      "post": {
        "description": "Checks that the organization can send what the sequence sends, then turns it on. The\nsequence starts enrolling and sending at once. When it cannot send, answers 400\n`sequence_activation_blocked` with `blockers`, and nothing changes. `activation_warnings`\non success name email setup that may keep mail from landing. A paused sequence stays paused:\ncall `sequences_resume` for it. For a broadcast, call `sequences_start_schedule`: a broadcast\nsends nothing until its schedule starts.",
        "operationId": "sequences_activate",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceDto"
                }
              }
            }
          },
          "400": {
            "description": "`sequence_activation_blocked`: `blockers` says what to fix",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Turn a sequence on",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [
          "sequences"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/pause": {
      "post": {
        "description": "Holds every enrollment where it is. Nothing sends and nobody new enrolls until `sequences_resume`. Only an active sequence can pause, and not a broadcast or a sequence Iris manages. Pause a broadcast with `sequences_pause_schedule`.",
        "operationId": "sequences_pause",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceDto"
                }
              }
            }
          },
          "400": {
            "description": "The sequence is not active, is a broadcast, or is managed by Iris"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Pause a sequence",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [
          "sequences"
        ],
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/resume": {
      "post": {
        "description": "Each enrollment continues from its current step. Due times move later by the time spent paused, so the spacing stays the same. A sequence that is not paused answers 409 `sequence_not_paused` and nothing changes.",
        "operationId": "sequences_resume",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`sequence_not_paused`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Resume a paused sequence",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [
          "sequences"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/duplicate": {
      "post": {
        "description": "Copies the steps, edges, triggers, exit conditions and send window into a new inactive draft, and returns the draft.",
        "operationId": "sequences_duplicate",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdempotencyKeyDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: the key was sent before with other details, or before the caller’s access changed. `idempotency_in_progress`: the first call with the key is still running. `idempotency_outcome_unknown`: the first call failed after it started and may have taken effect, so read the current state before you retry with a new key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "`idempotency_unavailable`: an `idempotency_key` was sent, but the store that keeps it is down. The call did not run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Copy a sequence into a new draft",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [
          "sequences"
        ],
        "x-iris-idempotent": true,
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/enrollments/{enrollmentId}": {
      "get": {
        "description": "The enrollment, each step run in the order it ran, and each event (sent, delivered, opened, clicked, replied, bounced) oldest first.",
        "operationId": "sequences_get_enrollment",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "enrollmentId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentDetailDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:read` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such sequence in this organization\n\nNo such enrollment in this sequence",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Get the send log of one enrollment",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-scope": "sequences:read",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/enrollments/{enrollmentId}/cancel": {
      "post": {
        "description": "Cancels the enrollment and its pending sends, and returns it. Safe to retry: an enrollment that already ended is returned as it is.",
        "operationId": "sequences_cancel_enrollment",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "enrollmentId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such sequence in this organization\n\nNo such enrollment in this sequence",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Remove a contact from a sequence",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [
          "sequences"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/analytics": {
      "get": {
        "description": "Event counts per step and for the whole sequence. Read `email_delivery_reporting` before\nyou report email numbers: `unsupported` means delivered and bounced are unknown, not zero.",
        "operationId": "sequences_analytics",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceAnalyticsDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:read` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Get the send totals of a sequence",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-scope": "sequences:read",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/steps/{stepKey}/test": {
      "post": {
        "description": "Sends the saved email or SMS of one step once, to a contact or to an address you give. It sends a real\nmessage, and nothing is recorded: no enrollment, no send log row, no analytics event. The dashboard\nlets an owner or admin send a test to any address, and so does this: send `to_email` or `to_phone`\nonly to an address or number the user owns, never to a customer. With `contact_id` the step variables\nfill from that contact and the message goes to the contact, unless you also send `to_email` or\n`to_phone`. Without it the variables are empty. Opt-out and consent checks apply to the recipient. A\nrefused or failed send answers 200 with `success` false and `error`. A wait or task step answers 400.\nSave the step first: the test sends what is saved. Ask the user first.",
        "operationId": "sequences_test_step",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "stepKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "The `step_key` of the step, as `sequences_get` lists it. At most 128 characters."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SequenceTestStepDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceTestStepResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, no address for the channel, or not an email or SMS step"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such step, or no such contact in this organization\n\nNo such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: the key was sent before with other details, or before the caller’s access changed. `idempotency_in_progress`: the first call with the key is still running. `idempotency_outcome_unknown`: the first call failed after it started and may have taken effect, so read the current state before you retry with a new key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "503": {
            "description": "`idempotency_unavailable`: an `idempotency_key` was sent, but the store that keeps it is down. The call did not run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Send a test of one step",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [],
        "x-iris-confirm": true,
        "x-iris-idempotent": true,
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/schedule": {
      "get": {
        "description": "A broadcast sends on its schedule. Answers the schedule and one page of its runs, newest\nfirst. Each run is one send to the audience. A broadcast with no schedule answers 404: set one\nwith `sequences_set_schedule`. An automation has no schedule. `page` is at most 1000 and\n`limit` at most 100. A `page` well past the last run can answer 400.",
        "operationId": "sequences_get_schedule",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "1-based page number, at most 1000",
            "schema": {
              "minimum": 1,
              "maximum": 1000,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size (capped at 100)",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceSchedulePageDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid paging, or a `page` well past the last run"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:read` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "This broadcast has no schedule\n\nNo such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Get a broadcast's send schedule and its runs",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-scope": "sequences:read",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      },
      "put": {
        "description": "Creates or replaces the schedule of a broadcast. `once` needs `send_at`. `recurring` needs an\n`rrule` such as `FREQ=WEEKLY;BYDAY=MO;BYHOUR=9;BYMINUTE=0`, read in `timezone`. The rule takes only\n`FREQ` (`DAILY`, `WEEKLY`, `MONTHLY`), `INTERVAL` (1 to 100), `BYDAY`, `BYMONTHDAY`, `BYSETPOS`,\n`BYHOUR` and `BYMINUTE`, with the limits on `rrule`. `starts_on` and `ends_on` are days from\n2000-01-01 to 2100-12-31. Anything else answers 400 naming the part. The schedule is\nsaved as `draft` and sends nothing until `sequences_start_schedule`. Setting it again puts a\nstarted schedule back to `draft`, so start it again. It also cancels every run that has not\nended, and every enrollment an earlier run made that is still active. An automation answers 400.",
        "operationId": "sequences_set_schedule",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SequenceScheduleSetDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceScheduleDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or the sequence is an automation"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Set when a broadcast sends",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [
          "sequences"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/schedule/start": {
      "post": {
        "description": "Starts a broadcast sending on its schedule: the schedule moves to `scheduled`, `next_fire_at`\nnames the first send, and the sequence turns on. This is how a broadcast goes live:\n`sequences_activate` only turns the sequence on, and a broadcast sends nothing until its\nschedule starts. Also restarts a paused schedule. Checks that the organization can send what\nthe broadcast sends. When it cannot, answers 400 `sequence_activation_blocked` with\n`blockers`, and nothing changes. A schedule with no future send answers 400. Otherwise a\nschedule that is not `draft` or `paused` answers 409. Ask the user first: this sends to every\ncontact in the audience.",
        "operationId": "sequences_start_schedule",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceScheduleStartDto"
                }
              }
            }
          },
          "400": {
            "description": "`sequence_activation_blocked`: `blockers` says what to fix. Or the schedule has no future send.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceErrorDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "This broadcast has no schedule\n\nNo such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "409": {
            "description": "The schedule is not `draft` or `paused`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Start a broadcast's schedule",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [
          "sequences"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/schedule/pause": {
      "post": {
        "description": "Stops new runs: no send starts while the schedule is `paused`. A run that is already sending\nkeeps sending: cancel it with `sequences_cancel_schedule_run`. This is not `sequences_pause`,\nwhich holds every enrollment of an automation in place. Start again with\n`sequences_start_schedule`.",
        "operationId": "sequences_pause_schedule",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceScheduleDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "This broadcast has no schedule\n\nNo such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Pause a broadcast's schedule",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [
          "sequences"
        ],
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/sequences/{sequenceId}/schedule/runs/{runId}/cancel": {
      "post": {
        "description": "Cancels every enrollment the run made that is still active, with their pending sends, and\nmoves the run to `cancelled` unless it already ended. `cancelled` counts those enrollments.\nTake the run id from `sequences_get_schedule`. A run with no active enrollment answers\n`cancelled: 0`. The schedule keeps its status: pause it to stop later runs.",
        "operationId": "sequences_cancel_schedule_run",
        "parameters": [
          {
            "name": "sequenceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "runId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceScheduleRunCancelDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "403": {
            "description": "The key does not carry the `sequences:write` scope; `required` names it. A member’s credential gets `insufficient_role`, except a manager holding the `sequences` power, at their locations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "No such run in this broadcast\n\nNo such sequence in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cancel one run of a broadcast",
        "tags": [
          "Sequences",
          "Public API"
        ],
        "x-iris-changes": [
          "sequences"
        ],
        "x-iris-confirm": true,
        "x-iris-scope": "sequences:write",
        "x-manager-power": "sequences",
        "x-member-access": "deny"
      }
    },
    "/api/v1/mcp": {
      "post": {
        "description": "The Iris MCP server, over stateless Streamable HTTP. Point an MCP client at this URL with\nthe key as a bearer token. Every other operation in this document is a tool named by its\noperationId, and `tools/list` shows only the tools the key’s scopes allow (and, for a\nmember’s credential, only the tools a member may call). A tool call runs\nthe REST operation, so it answers what the REST call answers. A failing call has\n`isError: true` and the REST error body as its text. Send\n`Accept: application/json, text/event-stream`. Answers 404 while the organization does\nnot have the MCP server turned on.",
        "operationId": "mcp_request",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The JSON-RPC answer"
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "404": {
            "description": "The MCP server is not turned on for this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds from this client address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicApiErrorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Send one MCP JSON-RPC message",
        "tags": [
          "Public API",
          "MCP"
        ],
        "x-iris-scope": null,
        "x-member-access": "open"
      }
    }
  },
  "info": {
    "title": "Iris Public API",
    "description": "The public, versioned API of Iris. Authenticate with an API key:\n`Authorization: Bearer iris_sk_…`. An owner or admin mints organization keys under\nOrganization → API keys, and any member mints personal keys under My agent access. Keys carry\nscopes; a key without a route’s scope gets a 403 with `{ \"error\": \"insufficient_scope\" }`.\nEach operation’s `x-iris-scope` names the scope it needs, or is null when any live key may call it.\n\nAgent clients that cannot hold a key (Claude Desktop, claude.ai, ChatGPT) use OAuth 2.1 with\nPKCE instead. They discover the authorization server from `/.well-known/oauth-protected-resource`,\nand send the access token the same way. Its scopes are the scopes above.\n\nAn OAuth token acts for the person who granted it, and a personal key for its owner. That\nperson’s current role and locations cap it. An owner or admin can turn a person’s agent access\noff, alone or by role: their personal keys and OAuth tokens then get the 401 until it is back on.\nEach operation’s `x-member-access` says what a MEMBER’s credential may do: `open` (call it),\n`scoped` (call it, limited to the member’s locations), `sms_setting` (call it while the\nmember’s SMS setting is on, limited to their own clients at their locations) or `deny` (403 with\n`{ \"error\": \"insufficient_role\" }`). An OWNER, an ADMIN and an organization key reach the\nwhole organization. `me_get` shows the person, role and locations behind the credential.\n\nEvery path is versioned. `v1` only ever grows: a breaking change ships as `v2`, and the\nold version keeps serving with `Deprecation` and `Sunset` headers until it is retired.",
    "version": "1.0.0",
    "contact": {}
  },
  "tags": [],
  "servers": [
    {
      "url": "https://api.iris.dotfun.co",
      "description": "REST base URL. The MCP server (Streamable HTTP) is https://api.iris.dotfun.co/api/v1/mcp, with every operation below as a tool named by its operationId."
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "An organization API key: the opaque `iris_sk_…` string shown once at creation. An OAuth access token from the Iris authorization server is accepted here too."
      }
    },
    "schemas": {
      "ContactCancelEventDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Event name whose enrollments should be cancelled for this contact.",
            "example": "cart_abandoned",
            "minLength": 1,
            "maxLength": 255
          },
          "reason": {
            "type": "string",
            "description": "Why the journey ended. Defaults to `goal_met`.",
            "enum": [
              "replied",
              "booked",
              "opted_out",
              "manual",
              "sequence_deactivated",
              "converted",
              "stage_reached",
              "goal_met",
              "schedule_cancelled",
              "assessment_retake"
            ],
            "example": "goal_met"
          }
        },
        "required": [
          "name"
        ]
      },
      "ContactEventDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Event name. Matched as free text against the `event_name` of every active `event` sequence in the organization.",
            "example": "trial_started",
            "minLength": 1,
            "maxLength": 255
          },
          "key": {
            "type": "string",
            "description": "Caller-owned idempotency key for this event. Stable for \"the same logical event\", so a redelivery is a no-op. Surrounding whitespace is trimmed.",
            "example": "trial_started:sub_01H8XYZ",
            "minLength": 1,
            "maxLength": 255
          },
          "supersedes": {
            "description": "Events whose running enrollments this one REPLACES. Cancelled after this event claims its `key` and before it enrolls, so a redelivery with the same `key` cancels nothing and enrolls nothing. Use this for mutually exclusive states of one subject; use the top-level `cancel_events` for an unconditional exit.",
            "maxItems": 10,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactCancelEventDto"
            }
          }
        },
        "required": [
          "name",
          "key"
        ]
      },
      "ContactUpsertDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Contact full name",
            "minLength": 1,
            "maxLength": 255
          },
          "email": {
            "type": "string",
            "description": "Contact email address — the upsert key, matched case-insensitively",
            "format": "email",
            "maxLength": 255
          },
          "phone": {
            "type": "string",
            "description": "Contact phone number. Stored in field_values; the contact itself stays email-keyed with phone_number NULL.",
            "maxLength": 255
          },
          "source": {
            "type": "string",
            "description": "Attribution source",
            "example": "web-form",
            "minLength": 1,
            "maxLength": 255
          },
          "fields": {
            "type": "object",
            "description": "Arbitrary key/value data merged into the contact's CRM field values. At most 200 keys. With assessment_abandoned, user_message_count must be a numeric nonnegative safe integer when present. Cohort routing uses this request's count: started requires a positive count, never_started requires zero, and missing counts match only unfiltered triggers.",
            "additionalProperties": true,
            "maxProperties": 200
          },
          "cancel_events": {
            "description": "Sequence events to CANCEL for this contact, unconditionally. Processed before `events`, and idempotent because a second call cancels nothing. Use it for a goal exit, such as ending a win-back nurture once the contact converts.",
            "maxItems": 10,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactCancelEventDto"
            }
          },
          "events": {
            "description": "Sequence events to FIRE for this contact, after the cancellations. Each event in turn claims its `key`, cancels the enrollments named in its `supersedes`, then enrolls. An event with no subscribing sequence leaves its key unspent, so a later retry still enrolls.",
            "maxItems": 10,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactEventDto"
            }
          }
        },
        "required": [
          "name",
          "email",
          "source"
        ]
      },
      "AssessmentAbandonmentReceiptDto": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "description": "Exact event key supplied by the producer"
          },
          "status": {
            "type": "string",
            "enum": [
              "accepted",
              "no_subscriber",
              "legacy_unverified"
            ]
          }
        },
        "required": [
          "key",
          "status"
        ]
      },
      "ContactUpsertResponseDto": {
        "type": "object",
        "properties": {
          "contactId": {
            "type": "string",
            "description": "CRM contact id the request wrote to",
            "format": "uuid"
          },
          "created": {
            "type": "boolean",
            "description": "true when a new contact was created, false when an existing one was updated"
          },
          "assessmentAbandonment": {
            "description": "Only accepted proves durable sequence enrollment. Other outcomes remain eligible for producer retry.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AssessmentAbandonmentReceiptDto"
            }
          }
        },
        "required": [
          "contactId",
          "created"
        ]
      },
      "PublicApiErrorDto": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "number",
            "description": "HTTP status code, repeated in the body",
            "example": 401
          },
          "timestamp": {
            "type": "string",
            "description": "When the failure was answered",
            "format": "date-time"
          },
          "path": {
            "type": "string",
            "description": "Path the request asked for, without its query string",
            "example": "/api/v1/contacts"
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation",
            "example": "Invalid API key"
          },
          "error": {
            "type": "string",
            "description": "Machine-readable error code. `insufficient_scope` or `insufficient_role` on a 403.",
            "example": "Unauthorized"
          },
          "required": {
            "type": "string",
            "description": "On a 403 only: the scope the key would need.",
            "example": "contacts:write"
          }
        },
        "required": [
          "statusCode",
          "timestamp",
          "path"
        ]
      },
      "ContactStageDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The stage value stored on the contact. Send it back as `stage_id`."
          },
          "name": {
            "type": "string",
            "description": "The label the pipeline shows"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "ContactSummaryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true,
            "description": "E.164"
          },
          "stage": {
            "nullable": true,
            "description": "Null when the organization has no pipeline stage field or the contact has no stage. Absent when the credential reads identity only: a MEMBER, or a MANAGER without the contacts power.",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/ContactStageDto"
              }
            ]
          },
          "custom_fields": {
            "type": "object",
            "additionalProperties": true,
            "description": "Custom field values keyed by field name. Absent when the credential reads identity only: a MEMBER, or a MANAGER without the contacts power."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Absent when the credential reads identity only: a MEMBER, or a MANAGER without the contacts power."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Absent when the credential reads identity only: a MEMBER, or a MANAGER without the contacts power."
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "phone"
        ]
      },
      "ContactPageDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactSummaryDto"
            }
          },
          "total": {
            "type": "number"
          },
          "page": {
            "type": "number"
          },
          "limit": {
            "type": "number"
          }
        },
        "required": [
          "items",
          "total",
          "page",
          "limit"
        ]
      },
      "ContactDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true,
            "description": "E.164"
          },
          "stage": {
            "nullable": true,
            "description": "Null when the organization has no pipeline stage field or the contact has no stage. Absent when the credential reads identity only: a MEMBER, or a MANAGER without the contacts power.",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/ContactStageDto"
              }
            ]
          },
          "custom_fields": {
            "type": "object",
            "additionalProperties": true,
            "description": "Custom field values keyed by field name. Absent when the credential reads identity only: a MEMBER, or a MANAGER without the contacts power."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Absent when the credential reads identity only: a MEMBER, or a MANAGER without the contacts power."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Absent when the credential reads identity only: a MEMBER, or a MANAGER without the contacts power."
          },
          "tags": {
            "description": "Tag names, sorted. Absent when the credential reads identity only: a MEMBER, or a MANAGER without the contacts power.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "notes_count": {
            "type": "number",
            "description": "Absent when the credential reads identity only: a MEMBER, or a MANAGER without the contacts power."
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "phone"
        ]
      },
      "ContactUpdateDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255
          },
          "phone": {
            "type": "string",
            "description": "E.164, e.g. +14155550100",
            "pattern": "^\\+[1-9]\\d{6,14}$"
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 255
          },
          "stage_id": {
            "type": "string",
            "description": "A stage `id` from the organization's pipeline"
          },
          "custom_fields": {
            "type": "object",
            "description": "Custom field values to merge, keyed by field name. An unknown name is a 400 that names it. At most 200 keys.",
            "additionalProperties": true,
            "maxProperties": 200
          }
        }
      },
      "ContactNoteCreateDto": {
        "type": "object",
        "properties": {
          "idempotency_key": {
            "type": "string",
            "maxLength": 255,
            "description": "Your own key for this call. A retry with the same key and the same details within 24 hours returns the first answer and does not run the call again. The same key with other details is a 409 `idempotency_key_reused`."
          },
          "body": {
            "type": "string",
            "pattern": "\\S",
            "maxLength": 10000
          }
        },
        "required": [
          "body"
        ]
      },
      "ContactNoteDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "body": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "contact_id",
          "body",
          "created_at"
        ]
      },
      "ContactTagCreateDto": {
        "type": "object",
        "properties": {
          "tag": {
            "type": "string",
            "description": "Tag name. Matched without regard to case or surrounding space; created on first use.",
            "maxLength": 120
          }
        },
        "required": [
          "tag"
        ]
      },
      "ContactTagsDto": {
        "type": "object",
        "properties": {
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "tags": {
            "description": "Every tag the contact carries after the change, sorted",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "contact_id",
          "tags"
        ]
      },
      "ContactSuppressDto": {
        "type": "object",
        "properties": {
          "channels": {
            "type": "array",
            "minItems": 1,
            "maxItems": 2,
            "items": {
              "type": "string",
              "enum": [
                "email",
                "sms"
              ]
            }
          },
          "reason": {
            "type": "string",
            "description": "Why, for example \"asked to stop on a call\". Written to the server log; not stored on the contact.",
            "maxLength": 255
          }
        },
        "required": [
          "channels"
        ]
      },
      "ContactSuppressResponseDto": {
        "type": "object",
        "properties": {
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "suppressed": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "email",
                "sms"
              ]
            }
          }
        },
        "required": [
          "contact_id",
          "suppressed"
        ]
      },
      "ContactStageListDto": {
        "type": "object",
        "properties": {
          "items": {
            "description": "In the order the pipeline shows them. Empty when the organization has no pipeline stage field.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactStageDto"
            }
          },
          "audience_field": {
            "type": "string",
            "nullable": true,
            "example": "field_values.stage",
            "description": "The audience rule `field` that tests a contact’s stage, with stage ids as values, for example with `eq` or `in`. Null when the organization has no pipeline stage field, or when the stage field name has a character other than a letter, digit or underscore. An audience rule cannot use that name."
          }
        },
        "required": [
          "items",
          "audience_field"
        ]
      },
      "ContactInteractionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "conversation_id": {
            "type": "string",
            "description": "The call, chat session or SMS thread this interaction belongs to"
          },
          "channel": {
            "type": "string",
            "enum": [
              "voice",
              "chat",
              "sms",
              "email"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "in_progress",
              "completed",
              "abandoned"
            ]
          },
          "started_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "location_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "appointment_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "The appointment this interaction booked, if any"
          },
          "captured_fields": {
            "type": "object",
            "additionalProperties": true,
            "description": "What the assistant captured during the interaction, by field name. Absent when the credential reads identity only: a MEMBER, or a MANAGER without the contacts power."
          }
        },
        "required": [
          "id",
          "contact_id",
          "conversation_id",
          "channel",
          "status",
          "started_at",
          "completed_at",
          "location_id",
          "appointment_id"
        ]
      },
      "ContactInteractionPageDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactInteractionDto"
            }
          },
          "total": {
            "type": "number"
          },
          "page": {
            "type": "number"
          },
          "limit": {
            "type": "number"
          }
        },
        "required": [
          "items",
          "total",
          "page",
          "limit"
        ]
      },
      "ContactNoteItemDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "body": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "user",
              "zapier",
              "system"
            ],
            "description": "Who wrote it: a team member (`user`), Zapier, or the system. Notes added through the API show as `system`."
          },
          "author_user_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "The team member who wrote it. Null for a Zapier or system note."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "body",
          "source",
          "author_user_id",
          "created_at"
        ]
      },
      "ContactNotePageDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactNoteItemDto"
            }
          },
          "total": {
            "type": "number"
          },
          "page": {
            "type": "number"
          },
          "limit": {
            "type": "number"
          }
        },
        "required": [
          "items",
          "total",
          "page",
          "limit"
        ]
      },
      "SequenceSummaryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "The name the organization gave the sequence"
          },
          "kind": {
            "type": "string",
            "enum": [
              "automation",
              "broadcast"
            ],
            "description": "'automation' fires per contact off a trigger; 'broadcast' fans an audience out on a schedule"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "inactive"
            ],
            "description": "'active' while the sequence enrolls and sends; 'paused' while it holds every enrollment in place; 'inactive' while it is off"
          },
          "location_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "The location the sequence runs for; null is organization-wide (IRIS-4185)"
          },
          "created_at": {
            "type": "string",
            "description": "When the sequence was created (ISO 8601)"
          }
        },
        "required": [
          "id",
          "name",
          "kind",
          "status",
          "location_id",
          "created_at"
        ]
      },
      "SequenceEnrollmentDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "contact_name": {
            "type": "string",
            "nullable": true,
            "description": "Null when the contact row was deleted"
          },
          "contact_email": {
            "type": "string",
            "nullable": true
          },
          "contact_phone": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "completed",
              "cancelled",
              "failed"
            ]
          },
          "current_step_index": {
            "type": "number",
            "description": "Zero-based index of the step the enrollment is on"
          },
          "loop_iteration": {
            "type": "number",
            "description": "Backward traversals made (0 when the sequence never loops)"
          },
          "total_iterations": {
            "type": "number",
            "description": "Completed visits across loop passes (0 = never looped)"
          },
          "enrolled_via": {
            "type": "string",
            "description": "What enrolled the contact, e.g. `lead_created` or `manual`"
          },
          "cancel_reason": {
            "type": "string",
            "nullable": true,
            "description": "Why a cancelled enrollment exited"
          },
          "next_run_at": {
            "type": "string",
            "nullable": true,
            "description": "When the next step was scheduled to fire. Read `next_step_due_at` first."
          },
          "variant_key": {
            "type": "string",
            "nullable": true,
            "description": "A/B arm assigned; null for non-variant"
          },
          "last_email_sent_at": {
            "type": "string",
            "nullable": true,
            "description": "When Iris last emailed this contact"
          },
          "last_email_subject": {
            "type": "string",
            "nullable": true,
            "description": "Subject of that last email"
          },
          "next_step_due_at": {
            "type": "string",
            "nullable": true,
            "description": "When the next step is actually due, from the live step run. Null when no step is pending. This, not `next_run_at`, is the authoritative next send time."
          },
          "created_at": {
            "type": "string",
            "description": "When the contact was enrolled (ISO 8601)"
          },
          "updated_at": {
            "type": "string",
            "description": "When the enrollment last changed (ISO 8601). Read with `status`: for a `completed` or `cancelled` enrollment this is when it ended."
          }
        },
        "required": [
          "id",
          "contact_id",
          "status",
          "current_step_index",
          "loop_iteration",
          "total_iterations",
          "enrolled_via",
          "created_at",
          "updated_at"
        ]
      },
      "SequenceEnrollmentPageDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceEnrollmentDto"
            }
          },
          "total": {
            "type": "number",
            "description": "Total matching enrollments across all pages"
          },
          "page": {
            "type": "number",
            "description": "1-based page number echoed back"
          },
          "limit": {
            "type": "number",
            "description": "Page size echoed back"
          }
        },
        "required": [
          "items",
          "total",
          "page",
          "limit"
        ]
      },
      "ContactEnrollmentDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "sequence_id": {
            "type": "string",
            "format": "uuid"
          },
          "sequence_name": {
            "type": "string",
            "nullable": true,
            "description": "Null when the sequence row was deleted"
          },
          "sequence_kind": {
            "type": "string",
            "nullable": true,
            "enum": [
              "automation",
              "broadcast"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "completed",
              "cancelled",
              "failed"
            ]
          },
          "current_step_index": {
            "type": "number",
            "description": "Zero-based index of the step the enrollment is on"
          },
          "loop_iteration": {
            "type": "number",
            "description": "Backward traversals made (0 when the sequence never loops)"
          },
          "total_iterations": {
            "type": "number",
            "description": "Completed visits across loop passes (0 = never looped)"
          },
          "cancel_reason": {
            "type": "string",
            "nullable": true,
            "description": "Why a cancelled enrollment exited"
          },
          "next_run_at": {
            "type": "string",
            "nullable": true,
            "description": "When the next step was scheduled to fire"
          },
          "enrolled_via": {
            "type": "string",
            "description": "What enrolled the contact"
          },
          "created_at": {
            "type": "string",
            "description": "When the contact was enrolled (ISO 8601)"
          },
          "updated_at": {
            "type": "string",
            "description": "When the enrollment last changed (ISO 8601). Read with `status`: for a `completed` or `cancelled` enrollment this is when it ended."
          }
        },
        "required": [
          "id",
          "sequence_id",
          "status",
          "current_step_index",
          "loop_iteration",
          "total_iterations",
          "enrolled_via",
          "created_at",
          "updated_at"
        ]
      },
      "ContactEnrollmentPageDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactEnrollmentDto"
            }
          },
          "total": {
            "type": "number",
            "description": "Total enrollments for the contact across all pages"
          },
          "page": {
            "type": "number",
            "description": "1-based page number echoed back"
          },
          "limit": {
            "type": "number",
            "description": "Page size echoed back"
          }
        },
        "required": [
          "items",
          "total",
          "page",
          "limit"
        ]
      },
      "MeOrganizationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Null only when the name could not be read"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "MeApiKeyDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "The name the key was given when it was minted"
          },
          "key_prefix": {
            "type": "string",
            "description": "The first characters of the key, as the dashboard shows them"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "contacts:read",
                "contacts:write",
                "sequences:read",
                "sequences:write",
                "appointments:read",
                "appointments:write",
                "conversations:read",
                "conversations:write",
                "calls:read",
                "audiences:read",
                "audiences:write",
                "forms:read"
              ]
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_used_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Refreshed at most every five minutes, so it can lag this request"
          },
          "location_ids": {
            "nullable": true,
            "description": "The locations a location-limited key reaches. Null for an organization-wide key, which reaches every location, and for a personal key, which reaches what its owner reaches.",
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "role": {
            "type": "string",
            "enum": [
              "MANAGER",
              "MEMBER"
            ],
            "nullable": true,
            "description": "The role the key acts at, with no person behind it: MANAGER or MEMBER. Each operation's `x-member-access` applies to it as to a person in that role, at `location_ids` when set. A location-limited key is always MANAGER or MEMBER. Null for an organization-wide key with no role, and for a personal key, which acts at its owner's role."
          },
          "powers": {
            "type": "array",
            "nullable": true,
            "description": "The manager powers a key with a role acts with, fixed when it was made. An operation marked `x-member-access: deny` answers 403 `insufficient_role` unless its `x-manager-power` is listed here. Empty for a MEMBER key. Null for a key with no role.",
            "items": {
              "type": "string",
              "enum": [
                "contacts",
                "location_settings",
                "sequences",
                "staff",
                "leader_schedules",
                "appointments",
                "access_levels"
              ]
            }
          }
        },
        "required": [
          "id",
          "name",
          "key_prefix",
          "scopes",
          "created_at",
          "last_used_at",
          "location_ids",
          "role",
          "powers"
        ]
      },
      "MeOauthClientDto": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string",
            "description": "The client id, or the URL of its metadata document"
          },
          "client_name": {
            "type": "string",
            "description": "The name the client registered with"
          },
          "scopes": {
            "type": "array",
            "description": "The scopes the owner granted",
            "items": {
              "type": "string",
              "enum": [
                "contacts:read",
                "contacts:write",
                "sequences:read",
                "sequences:write",
                "appointments:read",
                "appointments:write",
                "conversations:read",
                "conversations:write",
                "calls:read",
                "audiences:read",
                "audiences:write",
                "forms:read"
              ]
            }
          }
        },
        "required": [
          "client_id",
          "client_name",
          "scopes"
        ]
      },
      "MePrincipalDto": {
        "type": "object",
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "The person the credential acts for"
          },
          "role": {
            "type": "string",
            "enum": [
              "OWNER",
              "ADMIN",
              "MANAGER",
              "MEMBER"
            ],
            "description": "Their role in the organization now. A MANAGER or MEMBER cannot call an operation marked `x-member-access: deny`."
          },
          "location_ids": {
            "description": "The locations they reach: their own for a MEMBER, every location for an OWNER or ADMIN",
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "required": [
          "user_id",
          "role",
          "location_ids"
        ]
      },
      "MeScopeDto": {
        "type": "object",
        "properties": {
          "scope": {
            "type": "string",
            "enum": [
              "contacts:read",
              "contacts:write",
              "sequences:read",
              "sequences:write",
              "appointments:read",
              "appointments:write",
              "conversations:read",
              "conversations:write",
              "calls:read",
              "audiences:read",
              "audiences:write",
              "forms:read"
            ]
          },
          "label": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "required": [
          "scope",
          "label",
          "description"
        ]
      },
      "MeRateLimitDto": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "number",
            "description": "Requests allowed in one window"
          },
          "window_seconds": {
            "type": "number"
          },
          "bucket": {
            "type": "string",
            "enum": [
              "client_ip"
            ],
            "description": "What the limit counts against. It is the client address, not the key."
          }
        },
        "required": [
          "limit",
          "window_seconds",
          "bucket"
        ]
      },
      "MeResponseDto": {
        "type": "object",
        "properties": {
          "organization": {
            "$ref": "#/components/schemas/MeOrganizationDto"
          },
          "api_key": {
            "nullable": true,
            "description": "The calling key. Null for an OAuth access token.",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/MeApiKeyDto"
              }
            ]
          },
          "oauth_client": {
            "nullable": true,
            "description": "The connected client an OAuth access token was issued to. Null for an API key.",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/MeOauthClientDto"
              }
            ]
          },
          "principal": {
            "description": "The person behind the credential: the user who granted an OAuth access token, or the owner of a personal key. Absent for an organization key, which acts for the organization.",
            "allOf": [
              {
                "$ref": "#/components/schemas/MePrincipalDto"
              }
            ]
          },
          "scopes_available": {
            "description": "Every scope a key can be granted, with its label",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MeScopeDto"
            }
          },
          "rate_limit": {
            "$ref": "#/components/schemas/MeRateLimitDto"
          }
        },
        "required": [
          "organization",
          "api_key",
          "oauth_client",
          "scopes_available",
          "rate_limit"
        ]
      },
      "ServiceAddressDto": {
        "type": "object",
        "properties": {
          "line1": {
            "type": "string",
            "maxLength": 200
          },
          "line2": {
            "type": "string",
            "maxLength": 200
          },
          "city": {
            "type": "string",
            "maxLength": 120
          },
          "region": {
            "type": "string",
            "maxLength": 120,
            "description": "State, province or region"
          },
          "postal_code": {
            "type": "string",
            "maxLength": 32,
            "description": "Decides the territory, and so who can come"
          },
          "country_code": {
            "type": "string",
            "example": "US",
            "description": "ISO 3166-1 alpha-2"
          }
        }
      },
      "AppointmentDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string"
          },
          "start_time": {
            "type": "string",
            "format": "date-time"
          },
          "end_time": {
            "type": "string",
            "format": "date-time"
          },
          "timezone": {
            "type": "string",
            "description": "IANA time zone the appointment was booked in"
          },
          "status": {
            "type": "string",
            "enum": [
              "tentative",
              "confirmed",
              "cancelled",
              "completed",
              "no_show"
            ]
          },
          "location_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "The location the appointment is at"
          },
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "The contact the booking was made for, when it names one"
          },
          "offering_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "The service booked, from `locations_booking_options`, or null"
          },
          "team_member_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "The team member the appointment is with, or null"
          },
          "service_address": {
            "nullable": true,
            "description": "Where a home visit happens, or null",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/ServiceAddressDto"
              }
            ]
          },
          "attendee_name": {
            "type": "string",
            "nullable": true
          },
          "attendee_phone": {
            "type": "string",
            "nullable": true,
            "description": "E.164"
          },
          "attendee_email": {
            "type": "string",
            "nullable": true
          },
          "attendee_notes": {
            "type": "string",
            "nullable": true,
            "description": "Notes from the attendee, or null"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "The appointment notes, or null"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "recurring": {
            "type": "boolean",
            "description": "True when the appointment repeats. Cancel and reschedule refuse a repeating appointment with 409 `recurring_series_not_supported`."
          },
          "series_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "The repeating series the appointment belongs to, or null. Every occurrence of a series has the series id as its `id`."
          },
          "occurrence_start": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "In `appointments_list`, the start of this one occurrence of a repeating appointment. Null for an appointment that does not repeat, and in `appointments_get`."
          }
        },
        "required": [
          "id",
          "title",
          "start_time",
          "end_time",
          "timezone",
          "status",
          "location_id",
          "contact_id",
          "offering_id",
          "team_member_id",
          "service_address",
          "attendee_name",
          "attendee_phone",
          "attendee_email",
          "attendee_notes",
          "description",
          "created_at",
          "updated_at",
          "recurring",
          "series_id",
          "occurrence_start"
        ]
      },
      "AppointmentPageDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AppointmentDto"
            }
          },
          "total": {
            "type": "number"
          },
          "page": {
            "type": "number"
          },
          "limit": {
            "type": "number"
          }
        },
        "required": [
          "items",
          "total",
          "page",
          "limit"
        ]
      },
      "AvailabilityOfferingDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "duration_minutes": {
            "type": "number"
          }
        },
        "required": [
          "id",
          "name",
          "duration_minutes"
        ]
      },
      "AvailabilityTerritoryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "BookingTeamMemberDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Send it as `team_member_id`"
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "AvailabilitySlotDto": {
        "type": "object",
        "properties": {
          "start": {
            "type": "string",
            "format": "date-time",
            "description": "Send it as `start_time`"
          },
          "end": {
            "type": "string",
            "format": "date-time",
            "description": "Send it as `end_time`"
          },
          "team_members": {
            "description": "Who is free for this slot, in booking priority order. Empty at a location that is not staffed.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BookingTeamMemberDto"
            }
          }
        },
        "required": [
          "start",
          "end",
          "team_members"
        ]
      },
      "AvailabilityDto": {
        "type": "object",
        "properties": {
          "timezone": {
            "type": "string",
            "description": "IANA time zone of the location"
          },
          "offering": {
            "nullable": true,
            "description": "The service the slots are for",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/AvailabilityOfferingDto"
              }
            ]
          },
          "territory": {
            "nullable": true,
            "description": "The territory `postal_code` is in, or null",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/AvailabilityTerritoryDto"
              }
            ]
          },
          "slots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AvailabilitySlotDto"
            }
          }
        },
        "required": [
          "timezone",
          "offering",
          "territory",
          "slots"
        ]
      },
      "AppointmentCreateDto": {
        "type": "object",
        "properties": {
          "calendar_id": {
            "type": "string",
            "format": "uuid",
            "description": "A calendar from `calendars_list`. It sets the location. Send this or `location_id`, not both. Use it at a location that is not staffed."
          },
          "location_id": {
            "type": "string",
            "format": "uuid",
            "description": "A location from `locations_list`. Send this or `calendar_id`, not both. A staffed location needs this shape."
          },
          "offering_id": {
            "type": "string",
            "format": "uuid",
            "description": "With `location_id`: a service from `locations_booking_options`. The end time must match its `duration_minutes`."
          },
          "team_member_id": {
            "type": "string",
            "format": "uuid",
            "description": "With `location_id`: the team member to book. Leave it out to book the first team member who is free."
          },
          "service_address": {
            "description": "With `location_id`: where a home visit happens. Its postal code must be in a territory.",
            "allOf": [
              {
                "$ref": "#/components/schemas/ServiceAddressDto"
              }
            ]
          },
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "description": "The contact the appointment is for"
          },
          "start_time": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-24T15:00:00Z"
          },
          "end_time": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-24T15:30:00Z"
          },
          "title": {
            "type": "string",
            "default": "Appointment",
            "maxLength": 255
          },
          "idempotency_key": {
            "type": "string",
            "maxLength": 255,
            "description": "Your own key for this booking. A retry with the same key and the same details returns the first booking. The same key with other details is a 409."
          }
        },
        "required": [
          "contact_id",
          "start_time",
          "end_time",
          "idempotency_key"
        ]
      },
      "AppointmentUpdateDto": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 255
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Notes on the appointment. `null` clears them."
          },
          "attendee_name": {
            "type": "string",
            "nullable": true
          },
          "attendee_phone": {
            "type": "string",
            "nullable": true,
            "description": "E.164, e.g. +14155550100"
          },
          "attendee_email": {
            "type": "string",
            "nullable": true
          },
          "attendee_notes": {
            "type": "string",
            "nullable": true,
            "description": "Notes about the attendee"
          }
        }
      },
      "AppointmentRescheduleDto": {
        "type": "object",
        "properties": {
          "start_time": {
            "type": "string",
            "format": "date-time"
          },
          "end_time": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "start_time",
          "end_time"
        ]
      },
      "CalendarDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Send it as `calendar_id` to `appointments_create`"
          },
          "location_id": {
            "type": "string",
            "format": "uuid",
            "description": "The location the calendar books for"
          },
          "name": {
            "type": "string",
            "description": "The Google calendar’s name, or its id when Google does not answer"
          }
        },
        "required": [
          "id",
          "location_id",
          "name"
        ]
      },
      "LocationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Send it as `location_id`"
          },
          "name": {
            "type": "string"
          },
          "timezone": {
            "type": "string",
            "description": "IANA time zone of the location"
          },
          "staffed": {
            "type": "boolean",
            "description": "True when the location books by team member. Book it with `location_id`, never with a `calendar_id`."
          }
        },
        "required": [
          "id",
          "name",
          "timezone",
          "staffed"
        ]
      },
      "BookingOfferingDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Send it as `offering_id`"
          },
          "name": {
            "type": "string"
          },
          "duration_minutes": {
            "type": "number",
            "description": "The length of the appointment. `end_time` minus `start_time` must equal it."
          },
          "buffer_before_minutes": {
            "type": "number",
            "description": "Time kept free before the appointment"
          },
          "buffer_after_minutes": {
            "type": "number",
            "description": "Time kept free after the appointment"
          },
          "team_member_ids": {
            "description": "The team members who do this service here, in booking priority order",
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "required": [
          "id",
          "name",
          "duration_minutes",
          "buffer_before_minutes",
          "buffer_after_minutes",
          "team_member_ids"
        ]
      },
      "BookingOptionsDto": {
        "type": "object",
        "properties": {
          "staffed": {
            "type": "boolean",
            "description": "True when the location books by team member"
          },
          "offerings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BookingOfferingDto"
            }
          },
          "team_members": {
            "description": "Everyone bookable here, in booking priority order",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BookingTeamMemberDto"
            }
          }
        },
        "required": [
          "staffed",
          "offerings",
          "team_members"
        ]
      },
      "TerritoryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "location_id": {
            "type": "string",
            "format": "uuid",
            "description": "The location that serves the territory"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ]
          },
          "country_code": {
            "type": "string",
            "nullable": true,
            "description": "ISO 3166-1 alpha-2 country of the postal codes"
          },
          "postal_codes": {
            "description": "Normalized postal codes, sorted",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "team_member_ids": {
            "description": "The team members who cover the territory",
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "required": [
          "id",
          "name",
          "location_id",
          "status",
          "country_code",
          "postal_codes",
          "team_member_ids"
        ]
      },
      "ConversationSummaryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "sms",
              "chat"
            ]
          },
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "title": {
            "type": "string",
            "description": "The contact’s name or address, the email subject, or the chat visitor"
          },
          "preview": {
            "type": "string",
            "description": "The latest message, shortened. For a chat conversation it is the page the visitor chatted from, not a message: read the conversation for the transcript."
          },
          "last_message_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "id",
          "channel",
          "contact_id",
          "title",
          "preview",
          "last_message_at"
        ]
      },
      "ConversationPageDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConversationSummaryDto"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Pass it as `cursor` for the next page. Null on the last page."
          }
        },
        "required": [
          "items",
          "next_cursor"
        ]
      },
      "ConversationMessageDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ]
          },
          "from": {
            "type": "string",
            "nullable": true,
            "description": "Phone number or email address"
          },
          "to": {
            "type": "string",
            "nullable": true,
            "description": "Phone number or email address"
          },
          "subject": {
            "type": "string",
            "nullable": true,
            "description": "Email only"
          },
          "body": {
            "type": "string",
            "nullable": true,
            "description": "The text of the message"
          },
          "status": {
            "type": "string",
            "nullable": true,
            "description": "Delivery status"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "direction",
          "from",
          "to",
          "subject",
          "body",
          "status",
          "created_at"
        ]
      },
      "ConversationDetailDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "sms",
              "chat"
            ]
          },
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "title": {
            "type": "string",
            "description": "The contact’s phone number, the email subject, or the chat visitor (or the site they chatted on)"
          },
          "messages": {
            "description": "Oldest first. Every email or chat message, or the latest 50 SMS messages.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConversationMessageDto"
            }
          },
          "response_mode": {
            "type": "string",
            "enum": [
              "ai_auto",
              "human_auto",
              "human_manual"
            ],
            "nullable": true,
            "description": "Who answers the contact: `ai_auto` the AI, `human_auto` a person for now (the AI comes back after 30 minutes without a reply), `human_manual` a person until someone resumes the AI. Null for email."
          }
        },
        "required": [
          "id",
          "channel",
          "contact_id",
          "title",
          "messages",
          "response_mode"
        ]
      },
      "ConversationReplyDto": {
        "type": "object",
        "properties": {
          "idempotency_key": {
            "type": "string",
            "maxLength": 255,
            "description": "Your own key for this call. A retry with the same key and the same details within 24 hours returns the first answer and does not run the call again. The same key with other details is a 409 `idempotency_key_reused`."
          },
          "body": {
            "type": "string",
            "maxLength": 100000,
            "description": "The text of the reply. At most 1600 characters for SMS and 4000 for chat."
          }
        },
        "required": [
          "body"
        ]
      },
      "ConversationReplyResultDto": {
        "type": "object",
        "properties": {
          "conversation_id": {
            "type": "string",
            "format": "uuid"
          },
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "sms",
              "chat"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "sent",
              "partial_failed"
            ],
            "description": "`partial_failed`: a long SMS went out only in part. `messages` holds the parts that went out."
          },
          "messages": {
            "description": "The messages this reply stored",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConversationMessageDto"
            }
          }
        },
        "required": [
          "conversation_id",
          "channel",
          "status",
          "messages"
        ]
      },
      "ConversationResponseModeResultDto": {
        "type": "object",
        "properties": {
          "conversation_id": {
            "type": "string",
            "format": "uuid"
          },
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "sms",
              "chat"
            ]
          },
          "response_mode": {
            "type": "string",
            "enum": [
              "ai_auto",
              "human_auto",
              "human_manual"
            ]
          }
        },
        "required": [
          "conversation_id",
          "channel",
          "response_mode"
        ]
      },
      "IdempotencyKeyDto": {
        "type": "object",
        "properties": {
          "idempotency_key": {
            "type": "string",
            "maxLength": 255,
            "description": "Your own key for this call. A retry with the same key and the same details within 24 hours returns the first answer and does not run the call again. The same key with other details is a 409 `idempotency_key_reused`."
          }
        }
      },
      "SmsSendDto": {
        "type": "object",
        "properties": {
          "idempotency_key": {
            "type": "string",
            "maxLength": 255,
            "description": "Your own key for this call. A retry with the same key and the same details within 24 hours returns the first answer and does not run the call again. The same key with other details is a 409 `idempotency_key_reused`."
          },
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "description": "Send to this contact’s phone number"
          },
          "phone": {
            "type": "string",
            "description": "Send to this number, with its country code",
            "example": "+14155550100"
          },
          "body": {
            "type": "string",
            "maxLength": 1600
          }
        },
        "required": [
          "body"
        ]
      },
      "SentSmsDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "The stored message. Null when the provider accepted the send but Iris could not store it."
          },
          "to": {
            "type": "string",
            "description": "E.164"
          },
          "body": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "sent"
            ]
          }
        },
        "required": [
          "id",
          "to",
          "body",
          "status"
        ]
      },
      "SmsConsentDto": {
        "type": "object",
        "properties": {
          "idempotency_key": {
            "type": "string",
            "maxLength": 255,
            "description": "Your own key for this call. A retry with the same key and the same details within 24 hours returns the first answer and does not run the call again. The same key with other details is a 409 `idempotency_key_reused`."
          },
          "action": {
            "type": "string",
            "enum": [
              "opt_in",
              "opt_out"
            ]
          },
          "source": {
            "type": "string",
            "description": "Where the contact gave or withdrew consent, for example \"web form\". Kept with an opt-in.",
            "maxLength": 200
          }
        },
        "required": [
          "action"
        ]
      },
      "SmsConsentResultDto": {
        "type": "object",
        "properties": {
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "phone": {
            "type": "string",
            "description": "E.164"
          },
          "action": {
            "type": "string",
            "enum": [
              "opt_in",
              "opt_out"
            ]
          },
          "changed": {
            "type": "boolean",
            "description": "False when the contact was already in that state"
          }
        },
        "required": [
          "contact_id",
          "phone",
          "action",
          "changed"
        ]
      },
      "CallListItemDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The call id. Pass it to `calls_get`."
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ],
            "nullable": true
          },
          "external_number": {
            "type": "string",
            "nullable": true,
            "description": "The caller’s number, E.164"
          },
          "agent_number": {
            "type": "string",
            "nullable": true,
            "description": "The Iris number the call used, E.164"
          },
          "agent_name": {
            "type": "string",
            "description": "The Iris agent that took the call"
          },
          "outcome": {
            "type": "string",
            "enum": [
              "success",
              "failure",
              "unknown"
            ],
            "description": "Whether the call reached its goal"
          },
          "started_at": {
            "type": "string",
            "format": "date-time"
          },
          "duration_secs": {
            "type": "number"
          },
          "summary": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "direction",
          "external_number",
          "agent_number",
          "agent_name",
          "outcome",
          "started_at",
          "duration_secs",
          "summary"
        ]
      },
      "CallPageDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CallListItemDto"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Pass it as `cursor` for the next page. Null on the last page."
          }
        },
        "required": [
          "items",
          "next_cursor"
        ]
      },
      "CallTranscriptEntryDto": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "user",
              "agent"
            ],
            "description": "`user` is the caller"
          },
          "message": {
            "type": "string",
            "nullable": true
          },
          "time_in_call_secs": {
            "type": "number",
            "description": "Seconds into the call"
          }
        },
        "required": [
          "role",
          "message",
          "time_in_call_secs"
        ]
      },
      "CallDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The call id. Pass it to `calls_get`."
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ],
            "nullable": true
          },
          "external_number": {
            "type": "string",
            "nullable": true,
            "description": "The caller’s number, E.164"
          },
          "agent_number": {
            "type": "string",
            "nullable": true,
            "description": "The Iris number the call used, E.164"
          },
          "agent_name": {
            "type": "string",
            "description": "The Iris agent that took the call"
          },
          "outcome": {
            "type": "string",
            "enum": [
              "success",
              "failure",
              "unknown"
            ],
            "description": "Whether the call reached its goal"
          },
          "started_at": {
            "type": "string",
            "format": "date-time"
          },
          "duration_secs": {
            "type": "number"
          },
          "summary": {
            "type": "string",
            "nullable": true
          },
          "transcript": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CallTranscriptEntryDto"
            }
          },
          "has_audio": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "direction",
          "external_number",
          "agent_number",
          "agent_name",
          "outcome",
          "started_at",
          "duration_secs",
          "summary",
          "transcript",
          "has_audio"
        ]
      },
      "AudienceSummaryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "kind": {
            "type": "string",
            "enum": [
              "static",
              "dynamic"
            ],
            "description": "`static` lists hold the contacts added to them. `dynamic` ones match a filter, so members cannot be added."
          },
          "channel": {
            "type": "string",
            "enum": [
              "any",
              "email",
              "sms"
            ],
            "description": "The channel the audience is meant for"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "kind",
          "channel",
          "created_at"
        ]
      },
      "AudienceFilterRuleDto": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_.]+$",
            "maxLength": 200,
            "example": "total_calls",
            "description": "The contact field the rule tests. Either a contact column: `display_name`, `email`, `phone_number` (text); `total_calls` (number); `first_seen_at`, `last_seen_at`, `created_at`, `updated_at` (dates, compared as ISO 8601 strings). Or `field_values.<key>`, which reads a CRM custom field of this organization: `<key>` is the name of an enabled custom field (letters, digits and underscore only). A custom field of type number or currency compares as a number, date or datetime as an ISO 8601 string, boolean as true or false, and any other type as text. To filter by pipeline stage, use the `audience_field` that `contacts_list_stages` answers, with stage ids as values. Any other field makes `audiences_preview_count`, and `audiences_count` and `audiences_list_members` on a dynamic audience, answer 400. Create and update check only its format, at most 200 characters."
          },
          "op": {
            "type": "string",
            "enum": [
              "eq",
              "neq",
              "in",
              "not_in",
              "gt",
              "gte",
              "lt",
              "lte",
              "contains",
              "contains_any",
              "exists",
              "not_exists"
            ],
            "example": "gte",
            "description": "`eq`, `neq`: equal or not equal. `in`, `not_in`: equal to one of a list, or to none of it. `gt`, `gte`, `lt`, `lte`: greater or less than; only on number and date fields (`total_calls`, the four date columns, and custom fields of type number, currency, date or datetime). `contains`: the text holds the value, ignoring case. `contains_any`: the text holds any value of the list. Both work on the text columns and on custom fields, not on `total_calls` or dates. `exists`, `not_exists`: the field has a value, or has none. `eq`, `neq`, `in`, `not_in`, `exists` and `not_exists` work on every field."
          },
          "value": {
            "oneOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "string",
                      "maxLength": 1000
                    },
                    {
                      "type": "number"
                    },
                    {
                      "type": "boolean"
                    }
                  ]
                },
                "minItems": 1,
                "maxItems": 500
              }
            ],
            "example": 2,
            "description": "What the field is compared with. Leave it out for `exists` and `not_exists`. `in`, `not_in` and `contains_any` take a non-empty array of at most 500 strings, numbers or booleans. Every other op takes one string, number or boolean. A number field needs a number (or a numeric string). A string is at most 1000 characters. An object, or an array inside the array, answers 400."
          }
        },
        "required": [
          "field",
          "op"
        ]
      },
      "AudienceFilterDto": {
        "type": "object",
        "properties": {
          "match": {
            "type": "string",
            "enum": [
              "all",
              "any"
            ],
            "default": "all",
            "description": "`all`: a contact must meet every rule (AND). `any`: one rule is enough (OR)."
          },
          "rules": {
            "maxItems": 50,
            "description": "At most 50 rules, in one flat list: a rule holds no other rules. No rules, or an empty list, means every contact of the organization.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AudienceFilterRuleDto"
            }
          },
          "exclude_opted_out": {
            "type": "boolean",
            "default": true,
            "description": "Stored with the audience. Counts and contact lists do not apply it: opted-out contacts are removed when a message is sent."
          }
        }
      },
      "AudienceDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "kind": {
            "type": "string",
            "enum": [
              "static",
              "dynamic"
            ]
          },
          "channel": {
            "type": "string",
            "enum": [
              "any",
              "email",
              "sms"
            ],
            "description": "The channel the audience is meant for"
          },
          "definition": {
            "$ref": "#/components/schemas/AudienceFilterDto"
          },
          "is_archived": {
            "type": "boolean",
            "description": "An archived audience is left out of `audiences_list`"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "kind",
          "channel",
          "definition",
          "is_archived",
          "created_at",
          "updated_at"
        ]
      },
      "AudienceCreateDto": {
        "type": "object",
        "properties": {
          "idempotency_key": {
            "type": "string",
            "maxLength": 255,
            "description": "Your own key for this call. A retry with the same key and the same details within 24 hours returns the first answer and does not run the call again. The same key with other details is a 409 `idempotency_key_reused`."
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "maxLength": 2000
          },
          "kind": {
            "type": "string",
            "enum": [
              "static",
              "dynamic"
            ],
            "default": "dynamic",
            "description": "`dynamic` holds the contacts that match `definition`. `static` holds the contacts added to it. Fixed after create."
          },
          "channel": {
            "type": "string",
            "enum": [
              "any",
              "email",
              "sms"
            ],
            "default": "any",
            "description": "The channel the audience is meant for"
          },
          "definition": {
            "description": "Which contacts a dynamic audience holds. A static audience keeps its members instead, and ignores it.",
            "example": {
              "match": "all",
              "rules": [
                {
                  "field": "total_calls",
                  "op": "gte",
                  "value": 2
                },
                {
                  "field": "email",
                  "op": "exists"
                },
                {
                  "field": "field_values.plan",
                  "op": "in",
                  "value": [
                    "gold",
                    "platinum"
                  ]
                }
              ]
            },
            "allOf": [
              {
                "$ref": "#/components/schemas/AudienceFilterDto"
              }
            ]
          }
        },
        "required": [
          "name"
        ]
      },
      "AudienceUpdateDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "nullable": true,
            "maxLength": 2000,
            "description": "Null clears it"
          },
          "channel": {
            "type": "string",
            "enum": [
              "any",
              "email",
              "sms"
            ]
          },
          "definition": {
            "description": "Replaces the whole definition. Which contacts a dynamic audience holds. A static audience keeps its members instead, and ignores it.",
            "example": {
              "match": "all",
              "rules": [
                {
                  "field": "total_calls",
                  "op": "gte",
                  "value": 2
                },
                {
                  "field": "email",
                  "op": "exists"
                },
                {
                  "field": "field_values.plan",
                  "op": "in",
                  "value": [
                    "gold",
                    "platinum"
                  ]
                }
              ]
            },
            "allOf": [
              {
                "$ref": "#/components/schemas/AudienceFilterDto"
              }
            ]
          },
          "is_archived": {
            "type": "boolean",
            "description": "`false` restores an archived audience. Archive with `audiences_archive`."
          }
        }
      },
      "AudienceCountDto": {
        "type": "object",
        "properties": {
          "count": {
            "type": "number",
            "description": "How many contacts the audience holds, before opted-out and suppressed contacts are removed"
          }
        },
        "required": [
          "count"
        ]
      },
      "AudienceContactItemDto": {
        "type": "object",
        "properties": {
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "display_name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "phone_number": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "contact_id",
          "display_name",
          "email",
          "phone_number"
        ]
      },
      "AudienceContactPageDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AudienceContactItemDto"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Pass as `cursor` for the next page; null on the last"
          }
        },
        "required": [
          "items",
          "next_cursor"
        ]
      },
      "AudienceMemberAddDto": {
        "type": "object",
        "properties": {
          "contact_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "contact_id"
        ]
      },
      "AudienceMembershipDto": {
        "type": "object",
        "properties": {
          "audience_id": {
            "type": "string",
            "format": "uuid"
          },
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "member": {
            "type": "boolean",
            "description": "Whether the contact is a member after the call"
          },
          "changed": {
            "type": "boolean",
            "description": "False when the contact was already in that state"
          }
        },
        "required": [
          "audience_id",
          "contact_id",
          "member",
          "changed"
        ]
      },
      "FormSettingsSummaryDto": {
        "type": "object",
        "properties": {
          "target_sequence_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "The sequence every accepted submitter is enrolled in. Null: none."
          },
          "captcha_enabled": {
            "type": "boolean",
            "description": "Whether a submission needs a passing captcha"
          }
        },
        "required": [
          "target_sequence_id",
          "captcha_enabled"
        ]
      },
      "FormDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published",
              "archived"
            ]
          },
          "location_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "The location the form collects leads for. Null: all locations."
          },
          "settings": {
            "$ref": "#/components/schemas/FormSettingsSummaryDto"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "status",
          "location_id",
          "settings",
          "created_at",
          "updated_at"
        ]
      },
      "FormFieldOptionDto": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string"
          },
          "label": {
            "type": "string"
          }
        },
        "required": [
          "value",
          "label"
        ]
      },
      "FormFieldDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "key": {
            "type": "string",
            "description": "The key of this answer in a submission `payload`"
          },
          "label": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "email",
              "phone",
              "select",
              "checkbox",
              "hidden"
            ]
          },
          "placeholder": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          },
          "options": {
            "description": "The choices of a `select` field. Empty otherwise.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FormFieldOptionDto"
            }
          },
          "contact_target": {
            "type": "string",
            "nullable": true,
            "description": "Where the answer saves on the contact: `none`, a name part, `phone` or `field:<key>`. Null: by key."
          }
        },
        "required": [
          "id",
          "key",
          "label",
          "type",
          "placeholder",
          "required",
          "options",
          "contact_target"
        ]
      },
      "FormDetailDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published",
              "archived"
            ]
          },
          "location_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "The location the form collects leads for. Null: all locations."
          },
          "settings": {
            "$ref": "#/components/schemas/FormSettingsSummaryDto"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "fields": {
            "description": "In display order",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FormFieldDto"
            }
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "status",
          "location_id",
          "settings",
          "created_at",
          "updated_at",
          "fields"
        ]
      },
      "FormSubmissionContactDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "name",
          "email"
        ]
      },
      "FormSubmissionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "submitted_at": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "enum": [
              "accepted",
              "spam"
            ]
          },
          "contact_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid"
          },
          "contact": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/FormSubmissionContactDto"
              }
            ]
          },
          "contact_created": {
            "type": "boolean",
            "nullable": true,
            "description": "True: the submission created the contact. False: it updated one. Null: spam, or not recorded."
          },
          "sequence_enrollment_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "The enrollment this submission started"
          },
          "sequence_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "The sequence of that enrollment"
          },
          "payload": {
            "type": "object",
            "additionalProperties": true,
            "description": "The submitted answers, keyed by the form’s field `key`s, as posted"
          }
        },
        "required": [
          "id",
          "submitted_at",
          "status",
          "contact_id",
          "contact",
          "contact_created",
          "sequence_enrollment_id",
          "sequence_id",
          "payload"
        ]
      },
      "FormSubmissionPageDto": {
        "type": "object",
        "properties": {
          "items": {
            "description": "Newest first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FormSubmissionDto"
            }
          },
          "total": {
            "type": "number",
            "description": "Submissions that match the filters, on every page"
          },
          "page": {
            "type": "number"
          },
          "limit": {
            "type": "number"
          }
        },
        "required": [
          "items",
          "total",
          "page",
          "limit"
        ]
      },
      "SequenceCapabilitiesDto": {
        "type": "object",
        "properties": {
          "multi_trigger_writes_enabled": {
            "type": "boolean",
            "description": "True when a sequence may carry more than one trigger"
          }
        },
        "required": [
          "multi_trigger_writes_enabled"
        ]
      },
      "SequenceTriggerEventOptionDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "source": {
            "type": "string"
          }
        },
        "required": [
          "name",
          "label",
          "description",
          "source"
        ]
      },
      "SequenceTriggerDescriptorDto": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "description": "The value for `trigger_type`"
          },
          "label": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "authorable": {
            "type": "boolean",
            "description": "Only an authorable trigger can start a new sequence"
          },
          "enrollment_mode": {
            "type": "string"
          },
          "consent_posture": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "available",
              "coming_soon"
            ]
          },
          "system_managed": {
            "type": "boolean"
          },
          "note": {
            "type": "string",
            "nullable": true
          },
          "event_options": {
            "description": "Known event names, on the `event` trigger only",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceTriggerEventOptionDto"
            }
          }
        },
        "required": [
          "key",
          "label",
          "description",
          "authorable",
          "enrollment_mode",
          "consent_posture",
          "status",
          "system_managed"
        ]
      },
      "SendScheduleDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Use as `send_schedule_id` on `sequences_create` or `sequences_update`"
          },
          "name": {
            "type": "string"
          },
          "weekdays": {
            "description": "Days a send may go out: 0 is Sunday, 6 is Saturday",
            "type": "array",
            "items": {
              "type": "number"
            }
          },
          "start_minute": {
            "type": "number",
            "description": "First minute of the day a send may go out (0 to 1439)"
          },
          "end_minute": {
            "type": "number",
            "description": "Last minute of the day, exclusive (1 to 1440)"
          },
          "timezone_mode": {
            "type": "string",
            "enum": [
              "contact",
              "organization"
            ],
            "description": "Whose clock the window is read in: the contact’s or the organization’s"
          },
          "skip_holidays": {
            "type": "boolean"
          },
          "holiday_calendar": {
            "type": "string",
            "enum": [
              "US"
            ]
          },
          "randomize_minutes": {
            "type": "number",
            "description": "Minutes of random delay added to each send"
          },
          "is_default": {
            "type": "boolean",
            "description": "The window a sequence with no `send_schedule_id` uses"
          }
        },
        "required": [
          "id",
          "name",
          "weekdays",
          "start_minute",
          "end_minute",
          "timezone_mode",
          "skip_holidays",
          "holiday_calendar",
          "randomize_minutes",
          "is_default"
        ]
      },
      "SendSchedulePageDto": {
        "type": "object",
        "properties": {
          "items": {
            "description": "Default window first, then by name",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SendScheduleDto"
            }
          },
          "total": {
            "type": "number",
            "description": "Send windows across every page"
          },
          "page": {
            "type": "number"
          },
          "limit": {
            "type": "number"
          }
        },
        "required": [
          "items",
          "total",
          "page",
          "limit"
        ]
      },
      "SequenceVariableTokenDto": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Write it as `{{token}}`"
          },
          "label": {
            "type": "string"
          }
        },
        "required": [
          "token",
          "label"
        ]
      },
      "SequenceVariableGroupDto": {
        "type": "object",
        "properties": {
          "group": {
            "type": "string"
          },
          "tokens": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceVariableTokenDto"
            }
          }
        },
        "required": [
          "group",
          "tokens"
        ]
      },
      "SequenceVariableCatalogDto": {
        "type": "object",
        "properties": {
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceVariableGroupDto"
            }
          }
        },
        "required": [
          "groups"
        ]
      },
      "SequenceConditionSignalDto": {
        "type": "object",
        "properties": {
          "signal": {
            "type": "string",
            "description": "The `signal` of a condition"
          },
          "label": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "exit_available": {
            "type": "boolean",
            "description": "Usable in an exit condition"
          },
          "routing_status": {
            "type": "string",
            "enum": [
              "available",
              "coming_soon"
            ],
            "description": "Usable on a branch edge"
          },
          "routable": {
            "type": "boolean",
            "description": "False when the signal can never route a branch"
          },
          "note": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "signal",
          "label",
          "description",
          "exit_available",
          "routing_status",
          "routable"
        ]
      },
      "SequenceTriggerDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "config": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "type",
          "config"
        ]
      },
      "SendWindowDto": {
        "type": "object",
        "properties": {
          "start_minute": {
            "type": "number"
          },
          "end_minute": {
            "type": "number"
          }
        },
        "required": [
          "start_minute",
          "end_minute"
        ]
      },
      "SequenceStepDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "step_key": {
            "type": "string",
            "description": "Stable id of the step. Edges name steps by it."
          },
          "step_index": {
            "type": "number"
          },
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "sms",
              "wait",
              "task"
            ]
          },
          "delay_minutes": {
            "type": "number"
          },
          "timing_mode": {
            "type": "string",
            "enum": [
              "relative",
              "anchor"
            ],
            "description": "`relative` runs `delay_minutes` after the previous step. `anchor` runs `offset_minutes` from an event."
          },
          "offset_minutes": {
            "type": "number",
            "nullable": true
          },
          "subject_template": {
            "type": "string",
            "nullable": true
          },
          "body_template": {
            "type": "string",
            "nullable": true
          },
          "preheader_template": {
            "type": "string",
            "nullable": true
          },
          "body_document": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "ai_enabled": {
            "type": "boolean"
          },
          "ai_prompt": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "step_key",
          "step_index",
          "channel",
          "delay_minutes",
          "timing_mode",
          "ai_enabled"
        ]
      },
      "SequenceEdgeDto": {
        "type": "object",
        "properties": {
          "from_step_key": {
            "type": "string"
          },
          "to_step_key": {
            "type": "string",
            "nullable": true,
            "description": "Null ends the sequence"
          },
          "condition": {
            "type": "object",
            "additionalProperties": true,
            "description": "The routing condition in the condition DSL. Loop and A/B edges carry `maxIterations` and `variant` here."
          },
          "priority": {
            "type": "number"
          }
        },
        "required": [
          "from_step_key",
          "condition",
          "priority"
        ]
      },
      "SequenceExitConditionDto": {
        "type": "object",
        "properties": {
          "condition": {
            "type": "object",
            "additionalProperties": true
          },
          "cancel_reason": {
            "type": "string"
          }
        },
        "required": [
          "condition",
          "cancel_reason"
        ]
      },
      "SequenceVariableWarningDto": {
        "type": "object",
        "properties": {
          "step_index": {
            "type": "number"
          },
          "field": {
            "type": "string",
            "enum": [
              "subject",
              "preheader",
              "body"
            ]
          },
          "unknown_variables": {
            "description": "Variables the organization does not have",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "step_index",
          "field",
          "unknown_variables"
        ]
      },
      "SequenceActivationWarningDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "channel": {
            "type": "string",
            "nullable": true,
            "enum": [
              "email",
              "sms"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "message"
        ]
      },
      "SequenceDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "kind": {
            "type": "string",
            "enum": [
              "automation",
              "broadcast"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "inactive"
            ],
            "description": "`active` sends. `paused` holds every enrollment in place. `inactive` is off."
          },
          "paused_at": {
            "type": "string",
            "nullable": true,
            "description": "When it was paused. Null unless paused."
          },
          "trigger_type": {
            "type": "string"
          },
          "trigger_config": {
            "type": "object",
            "additionalProperties": true
          },
          "triggers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceTriggerDto"
            }
          },
          "audience_id": {
            "type": "string",
            "nullable": true
          },
          "send_schedule_id": {
            "type": "string",
            "nullable": true
          },
          "location_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "The location the sequence runs for; null is organization-wide"
          },
          "send_window": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/SendWindowDto"
              }
            ]
          },
          "is_system_managed": {
            "type": "boolean",
            "description": "A platform sequence. Its copy can change, but its trigger, kind, steps and timing cannot."
          },
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceStepDto"
            }
          },
          "edges": {
            "description": "Empty for a straight sequence",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceEdgeDto"
            }
          },
          "exit_conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceExitConditionDto"
            }
          },
          "variable_warnings": {
            "description": "Unknown `{{variables}}`. Advice only.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceVariableWarningDto"
            }
          },
          "activation_warnings": {
            "description": "Only on the write that turned the sequence on: email setup that may keep mail from landing",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceActivationWarningDto"
            }
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "kind",
          "status",
          "trigger_type",
          "trigger_config",
          "triggers",
          "location_id",
          "is_system_managed",
          "steps",
          "edges",
          "exit_conditions",
          "variable_warnings",
          "created_at",
          "updated_at"
        ]
      },
      "SequenceTriggerInputDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "A trigger `key` from `sequences_list_triggers` whose `authorable` is true"
          },
          "config": {
            "type": "object",
            "additionalProperties": true,
            "description": "Trigger settings"
          }
        },
        "required": [
          "type"
        ]
      },
      "SequenceStepInputDto": {
        "type": "object",
        "properties": {
          "step_index": {
            "type": "number",
            "minimum": 0,
            "description": "Zero-based position of the step"
          },
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "sms",
              "wait",
              "task"
            ],
            "description": "`email` and `sms` message the contact. `wait` only waits. `task` notifies the team: its subject is the title and its body the note."
          },
          "delay_minutes": {
            "type": "number",
            "minimum": 0,
            "description": "Minutes to wait after the previous step before this one runs"
          },
          "step_key": {
            "type": "string",
            "maxLength": 100,
            "description": "Stable id of the step. Edges name steps by it. Keep it when you edit a step. Generated when omitted."
          },
          "subject_template": {
            "type": "string",
            "description": "Email subject, or the task title. May use `{{variables}}`."
          },
          "body_template": {
            "type": "string",
            "description": "Message body, or the task note. May use `{{variables}}`."
          },
          "preheader_template": {
            "type": "string",
            "description": "Email preview text shown next to the subject in the inbox"
          },
          "body_document": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "A designed email body (EmailDocument v1). Omit to keep the stored one. Null clears it."
          },
          "ai_enabled": {
            "type": "boolean",
            "default": false,
            "description": "Let AI write the copy from `ai_prompt` at send time"
          },
          "ai_prompt": {
            "type": "string",
            "description": "What the AI should write, when `ai_enabled`"
          }
        },
        "required": [
          "step_index",
          "channel",
          "delay_minutes"
        ]
      },
      "SequenceExitConditionInputDto": {
        "type": "object",
        "properties": {
          "condition": {
            "type": "object",
            "additionalProperties": true,
            "description": "A condition in the DSL `sequences_get_condition_vocabulary` describes, e.g. `{ \"signal\": \"replied\" }`"
          },
          "cancel_reason": {
            "type": "string",
            "enum": [
              "goal_met",
              "converted",
              "stage_reached",
              "replied",
              "booked",
              "opted_out"
            ],
            "description": "Recorded on the enrollment when this exit fires"
          }
        },
        "required": [
          "condition",
          "cancel_reason"
        ]
      },
      "SequenceEdgeInputDto": {
        "type": "object",
        "properties": {
          "from_step_key": {
            "type": "string",
            "description": "`step_key` of the step the edge leaves"
          },
          "to_step_key": {
            "type": "string",
            "nullable": true,
            "description": "`step_key` it goes to. Null ends the sequence."
          },
          "condition": {
            "type": "object",
            "additionalProperties": true,
            "description": "A routing condition in the condition DSL. Omit for the fallback edge."
          },
          "priority": {
            "type": "number",
            "minimum": 0,
            "description": "Lower runs first. The first edge that matches wins."
          },
          "max_iterations": {
            "type": "number",
            "minimum": 1,
            "description": "Most passes through a loop. Required on an edge that goes back."
          },
          "variant_weight": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "A/B split weight. Every edge from the step must carry one, and they sum to 100."
          }
        },
        "required": [
          "from_step_key"
        ]
      },
      "SendWindowInputDto": {
        "type": "object",
        "properties": {
          "start_minute": {
            "type": "number",
            "minimum": 0,
            "maximum": 1439,
            "description": "Opens at this minute of the day, organization time. 540 is 09:00."
          },
          "end_minute": {
            "type": "number",
            "minimum": 1,
            "maximum": 1440,
            "description": "Closes at this minute (exclusive). 1080 is 18:00."
          }
        },
        "required": [
          "start_minute",
          "end_minute"
        ]
      },
      "SequenceCreateDto": {
        "type": "object",
        "properties": {
          "idempotency_key": {
            "type": "string",
            "maxLength": 255,
            "description": "Your own key for this call. A retry with the same key and the same details within 24 hours returns the first answer and does not run the call again. The same key with other details is a 409 `idempotency_key_reused`."
          },
          "name": {
            "type": "string",
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "maxLength": 2000
          },
          "trigger_type": {
            "type": "string",
            "description": "The primary trigger, a `key` from `sequences_list_triggers`"
          },
          "trigger_config": {
            "type": "object",
            "additionalProperties": true,
            "description": "Settings of the primary trigger"
          },
          "triggers": {
            "description": "Every trigger. The first is the primary one and must match `trigger_type` when both are sent.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceTriggerInputDto"
            }
          },
          "kind": {
            "type": "string",
            "enum": [
              "automation",
              "broadcast"
            ],
            "description": "`automation` runs off a trigger. `broadcast` sends to an audience."
          },
          "audience_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "For a broadcast: its audience. An automation stores none. An audience of another organization answers 404."
          },
          "send_schedule_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "A saved send schedule. Null uses the organization default."
          },
          "location_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "The location the sequence runs for: it enrolls only contacts at that location. Null or omitted is organization-wide, which only an owner or admin may set. A manager must name one of their locations. On an update, a move is refused while any enrollment, live or finished, holds a contact who is not at the new location."
          },
          "is_active": {
            "type": "boolean",
            "enum": [
              false
            ],
            "description": "Only `false`, and `true` is a 400. A new sequence is always an inactive draft. On an update, `false` turns the sequence off and cancels every enrollment. Turn a sequence on with `sequences_activate`, and hold contacts in place with `sequences_pause`."
          },
          "steps": {
            "description": "The ordered steps. On an update, replaces them all.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceStepInputDto"
            }
          },
          "exit_conditions": {
            "description": "Replaces the exit conditions. An enrollment stops when any of them is met.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceExitConditionInputDto"
            }
          },
          "edges": {
            "description": "Replaces the branch edges. Omit for a straight sequence.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceEdgeInputDto"
            }
          },
          "send_window": {
            "nullable": true,
            "description": "Hours of the day email and SMS may send. Null removes the window.",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/SendWindowInputDto"
              }
            ]
          }
        },
        "required": [
          "name",
          "trigger_type",
          "steps"
        ]
      },
      "SequenceUpdateDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "maxLength": 2000
          },
          "trigger_type": {
            "type": "string",
            "description": "The primary trigger, a `key` from `sequences_list_triggers`"
          },
          "trigger_config": {
            "type": "object",
            "additionalProperties": true,
            "description": "Settings of the primary trigger"
          },
          "triggers": {
            "description": "Every trigger. The first is the primary one and must match `trigger_type` when both are sent.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceTriggerInputDto"
            }
          },
          "kind": {
            "type": "string",
            "enum": [
              "automation",
              "broadcast"
            ],
            "description": "`automation` runs off a trigger. `broadcast` sends to an audience."
          },
          "audience_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "For a broadcast: its audience. An automation stores none. An audience of another organization answers 404."
          },
          "send_schedule_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "A saved send schedule. Null uses the organization default."
          },
          "location_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "The location the sequence runs for: it enrolls only contacts at that location. Null or omitted is organization-wide, which only an owner or admin may set. A manager must name one of their locations. On an update, a move is refused while any enrollment, live or finished, holds a contact who is not at the new location."
          },
          "is_active": {
            "type": "boolean",
            "enum": [
              false
            ],
            "description": "Only `false`, and `true` is a 400. A new sequence is always an inactive draft. On an update, `false` turns the sequence off and cancels every enrollment. Turn a sequence on with `sequences_activate`, and hold contacts in place with `sequences_pause`."
          },
          "steps": {
            "description": "The ordered steps. On an update, replaces them all.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceStepInputDto"
            }
          },
          "exit_conditions": {
            "description": "Replaces the exit conditions. An enrollment stops when any of them is met.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceExitConditionInputDto"
            }
          },
          "edges": {
            "description": "Replaces the branch edges. Omit for a straight sequence.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceEdgeInputDto"
            }
          },
          "send_window": {
            "nullable": true,
            "description": "Hours of the day email and SMS may send. Null removes the window.",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/SendWindowInputDto"
              }
            ]
          }
        }
      },
      "SequenceActivationBlockerDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Stable reason, e.g. `email_provider_not_configured`"
          },
          "channel": {
            "type": "string",
            "nullable": true,
            "enum": [
              "email",
              "sms"
            ]
          },
          "message": {
            "type": "string",
            "description": "What to fix, in a sentence"
          }
        },
        "required": [
          "code",
          "message"
        ]
      },
      "SequenceErrorDto": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "number",
            "description": "HTTP status code, repeated in the body",
            "example": 401
          },
          "timestamp": {
            "type": "string",
            "description": "When the failure was answered",
            "format": "date-time"
          },
          "path": {
            "type": "string",
            "description": "Path the request asked for, without its query string",
            "example": "/api/v1/contacts"
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation",
            "example": "Invalid API key"
          },
          "error": {
            "type": "string",
            "description": "Machine-readable error code",
            "example": "sequence_paused",
            "enum": [
              "sequence_activation_blocked",
              "sequence_inactive",
              "sequence_paused"
            ]
          },
          "required": {
            "type": "string",
            "description": "On a 403 only: the scope the key would need.",
            "example": "contacts:write"
          },
          "blockers": {
            "description": "On `sequence_activation_blocked` only",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceActivationBlockerDto"
            }
          }
        },
        "required": [
          "statusCode",
          "timestamp",
          "path"
        ]
      },
      "SequenceEnrollDto": {
        "type": "object",
        "properties": {
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "description": "The contact to enroll"
          },
          "email": {
            "type": "string",
            "description": "Or the email of the contact to enroll, matched without regard to case"
          },
          "start_step_key": {
            "type": "string",
            "maxLength": 128,
            "description": "Start at this `step_key` instead of the first step"
          }
        }
      },
      "EnrollmentDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "sequence_id": {
            "type": "string",
            "format": "uuid"
          },
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "completed",
              "cancelled",
              "failed"
            ]
          },
          "current_step_index": {
            "type": "number",
            "description": "Zero-based index of the step the enrollment is on"
          },
          "loop_iteration": {
            "type": "number"
          },
          "total_iterations": {
            "type": "number"
          },
          "next_run_at": {
            "type": "string",
            "nullable": true
          },
          "enrolled_via": {
            "type": "string",
            "description": "What enrolled the contact, e.g. `manual`"
          },
          "cancel_reason": {
            "type": "string",
            "nullable": true
          },
          "variant_key": {
            "type": "string",
            "nullable": true,
            "description": "A/B arm"
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string",
            "description": "For a cancelled or completed enrollment, when it ended"
          }
        },
        "required": [
          "id",
          "sequence_id",
          "contact_id",
          "status",
          "current_step_index",
          "loop_iteration",
          "total_iterations",
          "enrolled_via",
          "created_at",
          "updated_at"
        ]
      },
      "SequenceEnrollResultDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "enrolled",
              "skipped"
            ]
          },
          "reason": {
            "type": "string",
            "enum": [
              "already_enrolled"
            ],
            "description": "Why nothing changed: the contact is already active or paused in this sequence"
          },
          "enrollment": {
            "description": "The new enrollment, or the one the contact already has",
            "allOf": [
              {
                "$ref": "#/components/schemas/EnrollmentDto"
              }
            ]
          }
        },
        "required": [
          "status",
          "enrollment"
        ]
      },
      "EnrollmentStepRunDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "step_index": {
            "type": "number"
          },
          "loop_iteration": {
            "type": "number"
          },
          "channel": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "sending",
              "sent",
              "failed",
              "skipped",
              "cancelled"
            ]
          },
          "scheduled_at": {
            "type": "string"
          },
          "sent_at": {
            "type": "string",
            "nullable": true
          },
          "resolved_subject": {
            "type": "string",
            "nullable": true,
            "description": "The subject as sent"
          },
          "resolved_body": {
            "type": "string",
            "nullable": true,
            "description": "The body as sent"
          },
          "attempt_count": {
            "type": "number"
          },
          "last_error": {
            "type": "string",
            "nullable": true
          },
          "variant_key": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "step_index",
          "loop_iteration",
          "channel",
          "status",
          "scheduled_at",
          "attempt_count"
        ]
      },
      "EnrollmentEventDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "event_type": {
            "type": "string",
            "description": "sent, delivered, opened, clicked, replied, bounced and so on"
          },
          "occurred_at": {
            "type": "string"
          },
          "step_run_id": {
            "type": "string",
            "description": "The step run the event belongs to"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "id",
          "event_type",
          "occurred_at",
          "step_run_id",
          "metadata"
        ]
      },
      "EnrollmentDetailDto": {
        "type": "object",
        "properties": {
          "enrollment": {
            "$ref": "#/components/schemas/EnrollmentDto"
          },
          "step_runs": {
            "description": "In the order the steps ran",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnrollmentStepRunDto"
            }
          },
          "events": {
            "description": "Oldest first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnrollmentEventDto"
            }
          }
        },
        "required": [
          "enrollment",
          "step_runs",
          "events"
        ]
      },
      "SequenceAnalyticsIterationDto": {
        "type": "object",
        "properties": {
          "loop_iteration": {
            "type": "number"
          },
          "counts": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            }
          },
          "delivery_channels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "loop_iteration",
          "counts",
          "delivery_channels"
        ]
      },
      "SequenceAnalyticsStepDto": {
        "type": "object",
        "properties": {
          "step_index": {
            "type": "number"
          },
          "counts": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "Event counts: sent, delivered, opened, clicked, replied, bounced"
          },
          "delivery_channels": {
            "description": "The channels the counted sends went out on",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "iterations": {
            "description": "Per loop pass, when the step looped",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceAnalyticsIterationDto"
            }
          }
        },
        "required": [
          "step_index",
          "counts",
          "delivery_channels"
        ]
      },
      "SequenceAnalyticsDto": {
        "type": "object",
        "properties": {
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceAnalyticsStepDto"
            }
          },
          "rollup": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "Event counts for the whole sequence"
          },
          "delivery_channels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "variant_assignments": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "Contacts per A/B arm. Empty without a split."
          },
          "email_delivery_reporting": {
            "type": "string",
            "enum": [
              "supported",
              "unsupported",
              "not_applicable"
            ],
            "description": "`unsupported`: the email provider reports no delivery, so delivered and bounced read 0 whatever happened. `not_applicable`: no email sends."
          },
          "email_provider": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "steps",
          "rollup",
          "delivery_channels",
          "variant_assignments",
          "email_delivery_reporting"
        ]
      },
      "SequenceTestStepDto": {
        "type": "object",
        "properties": {
          "idempotency_key": {
            "type": "string",
            "maxLength": 255,
            "description": "Your own key for this call. A retry with the same key and the same details within 24 hours returns the first answer and does not run the call again. The same key with other details is a 409 `idempotency_key_reused`."
          },
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "description": "Fill the step variables from this contact. The contact must belong to this organization."
          },
          "to_email": {
            "type": "string",
            "format": "email",
            "maxLength": 254,
            "description": "The address that gets the email. Needed for an email step when `contact_id` is not sent."
          },
          "to_phone": {
            "type": "string",
            "maxLength": 32,
            "description": "The number that gets the text. Needed for an SMS step when `contact_id` is not sent."
          }
        }
      },
      "SequenceTestStepResultDto": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether the channel provider accepted the message"
          },
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "sms"
            ]
          },
          "provider_message_id": {
            "type": "string",
            "nullable": true,
            "description": "The provider message id when it was sent"
          },
          "error": {
            "type": "string",
            "nullable": true,
            "description": "Why the send failed, such as an opt-out or a provider error. Null when it was sent."
          },
          "reason_code": {
            "type": "string",
            "nullable": true,
            "description": "A stable reason when the send was held back, such as `opted_out` or `no_consent`"
          }
        },
        "required": [
          "success",
          "channel",
          "provider_message_id",
          "error",
          "reason_code"
        ]
      },
      "SequenceScheduleDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "sequence_id": {
            "type": "string",
            "format": "uuid"
          },
          "schedule_kind": {
            "type": "string",
            "enum": [
              "once",
              "recurring"
            ]
          },
          "send_at": {
            "type": "string",
            "nullable": true
          },
          "rrule": {
            "type": "string",
            "nullable": true
          },
          "timezone": {
            "type": "string"
          },
          "starts_on": {
            "type": "string",
            "nullable": true
          },
          "ends_on": {
            "type": "string",
            "nullable": true
          },
          "next_fire_at": {
            "type": "string",
            "nullable": true,
            "description": "The next send while the schedule is `scheduled`. Null on a `draft`."
          },
          "last_fired_at": {
            "type": "string",
            "nullable": true
          },
          "catchup_policy": {
            "type": "string",
            "enum": [
              "skip",
              "fire_once"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "scheduled",
              "sending",
              "paused",
              "completed",
              "cancelled"
            ],
            "description": "`draft` sends nothing. `scheduled` sends at `next_fire_at`. `paused` starts no new run."
          },
          "throttle_per_minute": {
            "type": "number",
            "nullable": true
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "sequence_id",
          "schedule_kind",
          "timezone",
          "catchup_policy",
          "status",
          "created_at",
          "updated_at"
        ]
      },
      "SequenceScheduleRunDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "occurrence_at": {
            "type": "string",
            "description": "When the run was due to send"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "fanning_out",
              "completed",
              "failed",
              "cancelled"
            ]
          },
          "recipients_total": {
            "type": "number",
            "description": "Audience contacts the run counted, suppressed ones included"
          },
          "recipients_enrolled": {
            "type": "number"
          },
          "recipients_suppressed": {
            "type": "number",
            "description": "Contacts the send rules left out: opted out, without SMS consent, with no phone or email for the channel, or a failed check"
          },
          "completed_at": {
            "type": "string",
            "nullable": true
          },
          "last_error": {
            "type": "string",
            "nullable": true,
            "description": "Why the run failed"
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "occurrence_at",
          "status",
          "recipients_total",
          "recipients_enrolled",
          "recipients_suppressed",
          "created_at"
        ]
      },
      "SequenceSchedulePageDto": {
        "type": "object",
        "properties": {
          "schedule": {
            "$ref": "#/components/schemas/SequenceScheduleDto"
          },
          "runs": {
            "description": "Newest first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceScheduleRunDto"
            }
          },
          "runs_total": {
            "type": "number",
            "description": "Runs across every page"
          },
          "page": {
            "type": "number"
          },
          "limit": {
            "type": "number"
          }
        },
        "required": [
          "schedule",
          "runs",
          "runs_total",
          "page",
          "limit"
        ]
      },
      "SequenceScheduleSetDto": {
        "type": "object",
        "properties": {
          "schedule_kind": {
            "type": "string",
            "enum": [
              "once",
              "recurring"
            ],
            "description": "`once` sends at `send_at`. `recurring` sends on `rrule`."
          },
          "send_at": {
            "type": "string",
            "format": "date-time",
            "maxLength": 40,
            "description": "When a `once` schedule sends. Required for `once`. A real calendar date-time ending in `Z` or an offset such as `-05:00`, for example `2026-11-01T09:00:00Z`. At most 40 characters."
          },
          "rrule": {
            "type": "string",
            "maxLength": 1000,
            "description": "An RFC 5545 rule such as `FREQ=WEEKLY;BYDAY=MO;BYHOUR=9;BYMINUTE=0`, read in `timezone`. Required for `recurring`. Only these parts, each at most once: `FREQ` (`DAILY`, `WEEKLY` or `MONTHLY`), `INTERVAL` (1 to 100), `BYDAY` (1 to 7 distinct weekdays `MO` to `SU`, no number; on `DAILY` only with `INTERVAL=1`), `BYMONTHDAY` (`MONTHLY` only, 1 to 31 distinct days from 1 to 31 or -31 to -1), `BYSETPOS` (`MONTHLY` only, `1` or `-1`), `BYHOUR` (one hour, 0 to 23) and `BYMINUTE` (one minute, 0 to 59). Any other part, such as `COUNT` or `UNTIL`, answers 400. End a series with `ends_on`."
          },
          "timezone": {
            "type": "string",
            "default": "UTC",
            "maxLength": 100,
            "description": "The IANA timezone `rrule` is read in"
          },
          "starts_on": {
            "type": "string",
            "format": "date",
            "maxLength": 10,
            "description": "The first day a recurring schedule may send (YYYY-MM-DD), from 2000-01-01 to 2100-12-31"
          },
          "ends_on": {
            "type": "string",
            "format": "date",
            "maxLength": 10,
            "description": "The last day a recurring schedule may send (YYYY-MM-DD), from 2000-01-01 to 2100-12-31 and not before `starts_on`"
          },
          "catchup_policy": {
            "type": "string",
            "enum": [
              "skip",
              "fire_once"
            ],
            "default": "skip",
            "description": "Sends a recurring schedule missed, for example while Iris was down: `skip` drops them, `fire_once` sends only the latest."
          },
          "throttle_per_minute": {
            "type": "number",
            "minimum": 1,
            "maximum": 2147483647,
            "description": "Stored for a planned limit on sends a minute, from 1 to 2147483647. Iris does not enforce it yet."
          }
        },
        "required": [
          "schedule_kind"
        ]
      },
      "SequenceScheduleStartDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "sequence_id": {
            "type": "string",
            "format": "uuid"
          },
          "schedule_kind": {
            "type": "string",
            "enum": [
              "once",
              "recurring"
            ]
          },
          "send_at": {
            "type": "string",
            "nullable": true
          },
          "rrule": {
            "type": "string",
            "nullable": true
          },
          "timezone": {
            "type": "string"
          },
          "starts_on": {
            "type": "string",
            "nullable": true
          },
          "ends_on": {
            "type": "string",
            "nullable": true
          },
          "next_fire_at": {
            "type": "string",
            "nullable": true,
            "description": "The next send while the schedule is `scheduled`. Null on a `draft`."
          },
          "last_fired_at": {
            "type": "string",
            "nullable": true
          },
          "catchup_policy": {
            "type": "string",
            "enum": [
              "skip",
              "fire_once"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "scheduled",
              "sending",
              "paused",
              "completed",
              "cancelled"
            ],
            "description": "`draft` sends nothing. `scheduled` sends at `next_fire_at`. `paused` starts no new run."
          },
          "throttle_per_minute": {
            "type": "number",
            "nullable": true
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "activation_warnings": {
            "description": "Email setup that may keep mail from landing. Omitted when there is none.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceActivationWarningDto"
            }
          }
        },
        "required": [
          "id",
          "sequence_id",
          "schedule_kind",
          "timezone",
          "catchup_policy",
          "status",
          "created_at",
          "updated_at"
        ]
      },
      "SequenceScheduleRunCancelDto": {
        "type": "object",
        "properties": {
          "cancelled": {
            "type": "number",
            "description": "The enrollments of the run that were still active and are now cancelled"
          }
        },
        "required": [
          "cancelled"
        ]
      }
    }
  }
}
